├── src ├── WebSite │ ├── wwwroot │ │ ├── robots.txt │ │ ├── sitemap.xml │ │ ├── ads.txt │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── img │ │ │ ├── face1.png │ │ │ ├── face2.png │ │ │ ├── gitee.png │ │ │ ├── github.png │ │ │ └── test.png │ │ ├── webfonts │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-duotone-900.woff2 │ │ │ ├── fa-light-300.woff2 │ │ │ ├── fa-regular-400.woff2 │ │ │ └── fa-solid-900.woff2 │ │ ├── service-worker.js │ │ ├── manifest.json │ │ ├── js │ │ │ ├── settings.js │ │ │ └── bootstrap-toc.js │ │ ├── css │ │ │ ├── vendor │ │ │ │ └── bootstrap-toc.css │ │ │ ├── responsive-helpers.css │ │ │ ├── site.css │ │ │ ├── animations.css │ │ │ ├── fluent-animations.css │ │ │ └── app.css │ │ └── service-worker.published.js │ ├── Services │ │ └── SeoService.cs │ ├── ViewModels │ │ ├── AskBotRequest.cs │ │ ├── Title2SlugRequest.cs │ │ ├── ArticleSummaryRequest.cs │ │ ├── PolyTranslateRequest.cs │ │ └── ConvertIconRequest.cs │ ├── _Imports.cs │ ├── Shared │ │ ├── HomeLayout.razor │ │ ├── SiteLayout.razor │ │ ├── Logo.razor │ │ ├── SettingBtns.razor.cs │ │ ├── MediaBox.razor │ │ ├── FriendLink.razor │ │ └── CommonMarkdown.razor │ ├── .config │ │ └── dotnet-tools.json │ ├── Options │ │ └── OpenAIOption.cs │ ├── Assets │ │ ├── 2024 │ │ │ └── 10 │ │ │ │ └── from-failure-to-success-how-to-delete-sq-lite-database-files-in-charp.md │ │ └── site │ │ │ ├── tools │ │ │ └── tools.json │ │ │ └── category.json │ ├── Pages │ │ ├── About.razor │ │ ├── Donation.razor │ │ └── TimeLine.razor │ ├── _Imports.razor │ ├── AppWeb.cs │ ├── FluentValidations │ │ └── ConvertIconRequestValidator.cs │ ├── Routes.razor │ ├── Jobs │ │ └── FileCleanerJob.cs │ ├── Dockerfile │ ├── appsettings.json │ ├── Controllers │ │ ├── WebController.cs │ │ └── AIController.cs │ ├── WebSite.csproj │ ├── Properties │ │ └── launchSettings.json │ ├── Program.cs │ └── App.razor ├── AntBlazor │ ├── _Imports.cs │ ├── _Imports.razor │ ├── AntAvatar.razor │ ├── AntForm.razor │ ├── AntSkeleton.razor │ ├── wwwroot │ │ └── css │ │ │ └── web.css │ ├── AntBlazor.csproj │ ├── Core │ │ ├── InputExtension.cs │ │ ├── BaseComponent.cs │ │ └── CssBuilder.cs │ ├── AntTextArea.razor │ ├── AntButton.razor │ ├── AntFormItem.razor │ ├── AntPassword.razor │ ├── AntTag.razor │ ├── AntModal.razor │ ├── AntInput.razor │ ├── AntAlert.razor │ ├── AntEmpty.razor │ ├── AntResult.razor │ ├── AntRadio.razor │ └── AntSearch.razor └── CodeWF │ ├── wwwroot │ ├── images │ │ ├── loading.gif │ │ ├── loading@2x.gif │ │ └── loading@3x.gif │ ├── js │ │ ├── iconconverter.js │ │ └── toc.js │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── editormd-logo.eot │ │ ├── editormd-logo.ttf │ │ ├── editormd-logo.woff │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── fontawesome-webfont.woff2 │ │ └── editormd-logo.svg │ ├── lib │ │ ├── codemirror │ │ │ └── addon │ │ │ │ ├── display │ │ │ │ ├── fullscreen.css │ │ │ │ ├── fullscreen.js │ │ │ │ ├── placeholder.js │ │ │ │ ├── rulers.js │ │ │ │ └── panel.js │ │ │ │ ├── search │ │ │ │ ├── matchesonscrollbar.css │ │ │ │ └── matchesonscrollbar.js │ │ │ │ ├── fold │ │ │ │ ├── foldgutter.css │ │ │ │ ├── indent-fold.js │ │ │ │ ├── markdown-fold.js │ │ │ │ └── comment-fold.js │ │ │ │ ├── dialog │ │ │ │ └── dialog.css │ │ │ │ ├── hint │ │ │ │ ├── show-hint.css │ │ │ │ ├── anyword-hint.js │ │ │ │ └── css-hint.js │ │ │ │ ├── mode │ │ │ │ ├── multiplex_test.js │ │ │ │ ├── loadmode.js │ │ │ │ └── overlay.js │ │ │ │ ├── lint │ │ │ │ ├── yaml-lint.js │ │ │ │ ├── json-lint.js │ │ │ │ ├── css-lint.js │ │ │ │ ├── coffeescript-lint.js │ │ │ │ └── lint.css │ │ │ │ ├── edit │ │ │ │ ├── trailingspace.js │ │ │ │ ├── continuelist.js │ │ │ │ └── matchtags.js │ │ │ │ ├── tern │ │ │ │ ├── worker.js │ │ │ │ └── tern.css │ │ │ │ ├── runmode │ │ │ │ ├── colorize.js │ │ │ │ └── runmode.js │ │ │ │ ├── scroll │ │ │ │ ├── simplescrollbars.css │ │ │ │ └── scrollpastend.js │ │ │ │ ├── selection │ │ │ │ ├── active-line.js │ │ │ │ └── selection-pointer.js │ │ │ │ ├── comment │ │ │ │ └── continuecomment.js │ │ │ │ └── merge │ │ │ │ └── merge.css │ │ └── jquery.flowchart.min.js │ ├── plugins │ │ ├── test-plugin │ │ │ └── test-plugin.js │ │ ├── plugin-template.js │ │ └── help-dialog │ │ │ └── help-dialog.js │ └── css │ │ └── toc.css │ ├── Models │ ├── ConstData.cs │ ├── PageData.cs │ ├── TimeLineItem.cs │ ├── AlbumItem.cs │ ├── CategoryItem.cs │ ├── ToolItem.cs │ ├── FriendLinkItem.cs │ ├── SitemapNode.cs │ ├── DocItem.cs │ └── BlogPost.cs │ ├── Shared │ ├── WechatPublicLink.razor │ ├── SearchBox.razor │ ├── CmsTitle.razor │ ├── UPostTags.razor │ ├── UPostItem.razor │ ├── UMenuBar.razor │ ├── CmsCard.razor │ ├── UPostCount.razor │ ├── UPostRank.razor │ ├── PostFooter.razor │ ├── UDocMenu.razor │ ├── UToolMenu.razor │ └── UPostInfo.razor │ ├── _Imports.razor │ ├── Pages │ ├── ListComponent.cs │ ├── Bbs │ │ ├── UWebSiteCount.razor │ │ ├── AlbumList.razor │ │ ├── CategoryList.razor │ │ ├── PostInfo.razor │ │ ├── Album.razor │ │ └── Category.razor │ ├── Docs │ │ └── Document.razor │ └── Tool │ │ ├── Web │ │ └── SlugifyString.razor │ │ └── Index.razor │ ├── _Imports.cs │ ├── Extensions │ ├── MarkdownExtension.cs │ └── ConstantUtil.cs │ ├── Options │ └── SiteOption.cs │ ├── CodeWF.csproj │ └── AppConfig.cs ├── .idea └── .idea.CodeWF │ └── .idea │ ├── .name │ ├── encodings.xml │ ├── vcs.xml │ ├── indexLayout.xml │ └── .gitignore ├── .dockerignore ├── Directory.Build.props ├── .github └── workflows │ └── jekyll-docker.yml ├── LICENSE └── CodeWF.sln /src/WebSite/wwwroot/robots.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/WebSite/wwwroot/sitemap.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.idea.CodeWF/.idea/.name: -------------------------------------------------------------------------------- 1 | CodeWF -------------------------------------------------------------------------------- /src/WebSite/Services/SeoService.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/WebSite/wwwroot/ads.txt: -------------------------------------------------------------------------------- 1 | google.com, pub-8748951917303002, DIRECT, f08c47fec0942fa0 -------------------------------------------------------------------------------- /src/AntBlazor/_Imports.cs: -------------------------------------------------------------------------------- 1 | global using Microsoft.AspNetCore.Components; 2 | global using Microsoft.JSInterop; -------------------------------------------------------------------------------- /src/WebSite/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/WebSite/wwwroot/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/favicon.png -------------------------------------------------------------------------------- /src/WebSite/wwwroot/img/face1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/img/face1.png -------------------------------------------------------------------------------- /src/WebSite/wwwroot/img/face2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/img/face2.png -------------------------------------------------------------------------------- /src/WebSite/wwwroot/img/gitee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/img/gitee.png -------------------------------------------------------------------------------- /src/WebSite/wwwroot/img/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/img/github.png -------------------------------------------------------------------------------- /src/WebSite/wwwroot/img/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/img/test.png -------------------------------------------------------------------------------- /src/WebSite/ViewModels/AskBotRequest.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite.ViewModels; 2 | 3 | public record AskBotRequest(string Content); -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/images/loading.gif -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/js/iconconverter.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/js/iconconverter.js -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/images/loading@2x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/images/loading@2x.gif -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/images/loading@3x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/images/loading@3x.gif -------------------------------------------------------------------------------- /src/WebSite/ViewModels/Title2SlugRequest.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite.ViewModels; 2 | 3 | public record Title2SlugRequest(string Content); -------------------------------------------------------------------------------- /src/CodeWF/Models/ConstData.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class ConstData 4 | { 5 | public const int PageSize = 10; 6 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/editormd-logo.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/editormd-logo.eot -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/editormd-logo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/editormd-logo.ttf -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/editormd-logo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/editormd-logo.woff -------------------------------------------------------------------------------- /src/CodeWF/Models/PageData.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public record PageData(int PageIndex, int PageSize, int Total, List Data); -------------------------------------------------------------------------------- /src/AntBlazor/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @using Microsoft.AspNetCore.Components.Routing 3 | @using AntBlazor.Core -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/WebSite/wwwroot/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/WebSite/wwwroot/webfonts/fa-duotone-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/webfonts/fa-duotone-900.woff2 -------------------------------------------------------------------------------- /src/WebSite/wwwroot/webfonts/fa-light-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/webfonts/fa-light-300.woff2 -------------------------------------------------------------------------------- /src/WebSite/wwwroot/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /src/WebSite/wwwroot/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/WebSite/wwwroot/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet9/CodeWF/HEAD/src/CodeWF/wwwroot/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/WebSite/ViewModels/ArticleSummaryRequest.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite.ViewModels; 2 | 3 | public record ArticleSummaryRequest(string Content, int Length = 200); -------------------------------------------------------------------------------- /src/WebSite/ViewModels/PolyTranslateRequest.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite.ViewModels; 2 | 3 | public record PolyTranslateRequest(string Content, List Languages); -------------------------------------------------------------------------------- /src/WebSite/_Imports.cs: -------------------------------------------------------------------------------- 1 | global using Known; 2 | global using CodeWF.Models; 3 | global using CodeWF.Services; 4 | global using WebSite; 5 | global using CodeWF; -------------------------------------------------------------------------------- /src/AntBlazor/AntAvatar.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 | 5 |
6 | 7 | @code { 8 | [Parameter] public string Src { get; set; } 9 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/display/fullscreen.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-fullscreen { 2 | position: fixed; 3 | top: 0; left: 0; right: 0; bottom: 0; 4 | height: auto; 5 | z-index: 9; 6 | } 7 | -------------------------------------------------------------------------------- /.idea/.idea.CodeWF/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/.idea.CodeWF/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/CodeWF/Shared/WechatPublicLink.razor: -------------------------------------------------------------------------------- 1 | @inject IOptions SiteOption 2 | 3 | 联系请关注微信公众号:@SiteOption.Value.WeChatName -------------------------------------------------------------------------------- /src/WebSite/Shared/HomeLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 4 | 5 |
6 | @Body 7 |
8 | 9 | -------------------------------------------------------------------------------- /src/WebSite/ViewModels/ConvertIconRequest.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite.ViewModels; 2 | 3 | public class ConvertIconRequest 4 | { 5 | public IFormFile SourceImage { get; set; } 6 | public uint[] ConvertSizes { get; set; } 7 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/SearchBox.razor: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | @code { 6 | [SupplyParameterFromQuery] public string Key { get; set; } 7 | } -------------------------------------------------------------------------------- /src/CodeWF/Models/TimeLineItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class TimeLineItem 4 | { 5 | public DateTime? Time { get; set; } 6 | public string? Title { get; set; } 7 | public string? Content { get; set; } 8 | } -------------------------------------------------------------------------------- /src/WebSite/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "8.0.0", 7 | "commands": [ 8 | "dotnet-ef" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/WebSite/Options/OpenAIOption.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite.Options; 2 | public class OpenAIOption 3 | { 4 | public string? Endpoint { get; set; } 5 | 6 | public string? Key { get; set; } 7 | 8 | public string? ChatModel { get; set; } 9 | } -------------------------------------------------------------------------------- /src/WebSite/Shared/SiteLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 5 |
6 | @Body 7 |
8 | 9 | 10 |
-------------------------------------------------------------------------------- /.idea/.idea.CodeWF/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/CodeWF/Models/AlbumItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class AlbumItem 4 | { 5 | public int Sort { get; set; } 6 | 7 | public string? Name { get; set; } 8 | public string? Memo { get; set; } 9 | public string? Slug { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CodeWF/Models/CategoryItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class CategoryItem 4 | { 5 | public int Sort { get; set; } 6 | 7 | public string? Name { get; set; } 8 | public string? Memo { get; set; } 9 | public string? Slug { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/search/matchesonscrollbar.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-search-match { 2 | background: gold; 3 | border-top: 1px solid orange; 4 | border-bottom: 1px solid orange; 5 | -moz-box-sizing: border-box; 6 | box-sizing: border-box; 7 | opacity: .5; 8 | } 9 | -------------------------------------------------------------------------------- /src/WebSite/wwwroot/service-worker.js: -------------------------------------------------------------------------------- 1 | // In development, always fetch from the network and do not enable offline support. 2 | // This is because caching would make development more difficult (changes would not 3 | // be reflected on the first load after each change). 4 | self.addEventListener('fetch', () => { }); 5 | -------------------------------------------------------------------------------- /src/CodeWF/Shared/CmsTitle.razor: -------------------------------------------------------------------------------- 1 |
2 | @if (!string.IsNullOrWhiteSpace(Icon)) 3 | { 4 | 5 | } 6 | @Title 7 |
8 | 9 | @code { 10 | [Parameter] public string Icon { get; set; } 11 | [Parameter] public string Title { get; set; } 12 | } -------------------------------------------------------------------------------- /.idea/.idea.CodeWF/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # Rider 忽略的文件 5 | /modules.xml 6 | /contentModel.xml 7 | /.idea.CodeWF.iml 8 | /projectSettingsUpdater.xml 9 | # 基于编辑器的 HTTP 客户端请求 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /src/CodeWF/Models/ToolItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class ToolItem 4 | { 5 | public string? Name { get; set; } 6 | public string? Memo { get; set; } 7 | public string? Slug { get; set; } 8 | public string? Repository { get; set; } 9 | public List? Children { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CodeWF/Models/FriendLinkItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class FriendLinkItem 4 | { 5 | public int Index { get; set; } 6 | 7 | public string? Title { get; set; } 8 | 9 | public string? Description { get; set; } 10 | 11 | public string? Link { get; set; } 12 | 13 | public string? Logo { get; set; } 14 | } -------------------------------------------------------------------------------- /src/CodeWF/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @using Microsoft.AspNetCore.Components.Routing 3 | @using AntBlazor 4 | @using Known 5 | @using Known.Extensions 6 | @using Known.Blazor 7 | @using Known.Components 8 | @using CodeWF.Extensions 9 | @using CodeWF.Shared 10 | @using CodeWF.Options 11 | @using Microsoft.Extensions.Options -------------------------------------------------------------------------------- /src/WebSite/Shared/Logo.razor: -------------------------------------------------------------------------------- 1 | @inject IOptions SiteOption 2 | 3 | 4 |
5 | @SiteOption.Value.AppTitle 6 | @SiteOption.Value.AppTitle 7 |
8 |
-------------------------------------------------------------------------------- /src/AntBlazor/AntForm.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Forms 2 | @inherits BaseComponent 3 | 4 | 5 | @ChildContent 6 | 7 | 8 | @code { 9 | private object model = new object(); 10 | 11 | [Parameter] public RenderFragment ChildContent { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CodeWF/Models/SitemapNode.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class SitemapNode 4 | { 5 | public string Url { get; set; } = null!; 6 | public DateTimeOffset LastModified { get; set; } 7 | public SitemapFrequency Frequency { get; set; } 8 | public double Priority { get; set; } 9 | } 10 | 11 | public enum SitemapFrequency 12 | { 13 | Monthly, 14 | Daily 15 | } -------------------------------------------------------------------------------- /src/WebSite/Assets/site/tools/tools.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Name": "Web", 4 | "Children": 5 | [ 6 | { 7 | "Name": "标题转URL", 8 | "Memo": "文章标题转URL友好的别名", 9 | "Slug": "slugify-string", 10 | "Repository": "https://github.com/dotnet9/CodeWF.EventBus" 11 | } 12 | ] 13 | } 14 | ] -------------------------------------------------------------------------------- /src/CodeWF/Models/DocItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class DocItem 4 | { 5 | public string? Name { get; set; } 6 | public string? Memo { get; set; } 7 | public string? Slug { get; set; } 8 | public string? Repository { get; set; } 9 | public string? Content { get; set; } 10 | public string? HtmlContent { get; set; } 11 | public List? Children { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/UPostTags.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 | @if (Tags?.Any() == true) 5 | { 6 | foreach (var tag in Tags) 7 | { 8 | @* @tag *@ 9 | @tag 10 | } 11 | } 12 |
13 | 14 | @code { 15 | [Parameter] public List? Tags { get; set; } 16 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntSkeleton.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 |
5 |

6 |
    7 |
  • 8 |
  • 9 |
  • 10 |
11 |
12 |
13 | 14 | @code { 15 | 16 | } -------------------------------------------------------------------------------- /src/AntBlazor/wwwroot/css/web.css: -------------------------------------------------------------------------------- 1 | @import "ant-design-blazor.css"; 2 | 3 | /*AntD*/ 4 | .ant-form-item-row {align-items:center;} 5 | .ant-form-horizontal .ant-form-item-label {width:80px;margin-right:10px;} 6 | .ant-form-horizontal .button {margin-left:90px;} 7 | .ant-modal-close {font-size:1.2rem;padding:1rem;} 8 | .ant-modal-close:hover {color:#a71e1e;} 9 | .ant-input-affix-wrapper {align-items:center;} 10 | .ant-input-affix-wrapper i {color:#ccc;margin-right:10px;} -------------------------------------------------------------------------------- /src/WebSite/Pages/About.razor: -------------------------------------------------------------------------------- 1 | @page "/about" 2 | 3 | @inherits BaseComponent 4 | @inject AppService AppService 5 | 6 | 7 | 8 | @code 9 | { 10 | private string? _markdown; 11 | private string? _html; 12 | 13 | protected override async Task OnInitAsync() 14 | { 15 | await base.OnInitAsync(); 16 | (_markdown, _html) = await AppService.ReadAboutAsync(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/WebSite/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @using Microsoft.AspNetCore.Components.Routing 3 | @using Microsoft.Extensions.Options 4 | @using Known 5 | @using Known.Extensions 6 | @using Known.Blazor 7 | @using Known.Components 8 | @using AntBlazor 9 | @using CodeWF.Services 10 | @using WebSite.Shared 11 | @using WebSite.Pages 12 | @using CodeWF.Pages.Bbs 13 | @using CodeWF.Options 14 | @using CodeWF.Shared 15 | @using CodeWF.Extensions 16 | -------------------------------------------------------------------------------- /src/WebSite/Pages/Donation.razor: -------------------------------------------------------------------------------- 1 | @page "/donation" 2 | 3 | @inherits BaseComponent 4 | @inject AppService AppService 5 | 6 | 7 | 8 | @code 9 | { 10 | private string? _markdown; 11 | private string? _html; 12 | 13 | protected override async Task OnInitAsync() 14 | { 15 | await base.OnInitAsync(); 16 | (_markdown, _html) = await AppService.ReadDonationAsync(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/CodeWF/Pages/ListComponent.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Pages; 2 | 3 | public class ListComponent : BaseComponent 4 | { 5 | protected PagingCriteria Criteria = new(); 6 | 7 | protected PagingResult Result = new(); 8 | 9 | [SupplyParameterFromQuery] public int Page { get; set; } 10 | 11 | protected override async Task OnInitAsync() 12 | { 13 | await base.OnInitAsync(); 14 | if (Page <= 0) 15 | Page = 1; 16 | Criteria.PageIndex = Page; 17 | } 18 | } -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md 26 | !**/.gitignore 27 | !.git/HEAD 28 | !.git/config 29 | !.git/packed-refs 30 | !.git/refs/heads/** -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeWF 4 | codewf.com 5 | 沙漠尽头的狼 6 | Copyright © 2024 codewf.com. All rights reserved. 7 | 码坊是使用.NET 10 Blazor开发的一个网站,这里有技术文章,有开源项目介绍,有在线工具使用: 码坊—文章启智,工具助力 8 | 0.0.1.0 9 | 0.0.1.0 10 | 0.0.1.0 11 | 0.0.1.0 12 | 13 | -------------------------------------------------------------------------------- /src/CodeWF/_Imports.cs: -------------------------------------------------------------------------------- 1 | global using CodeWF.Extensions; 2 | global using CodeWF.Models; 3 | global using CodeWF.Services; 4 | global using Known; 5 | global using Known.Blazor; 6 | global using Known.Extensions; 7 | global using Microsoft.AspNetCore.Components; 8 | global using Microsoft.Extensions.DependencyInjection; 9 | global using Markdig; 10 | global using CodeWF.Options; 11 | global using CodeWF.Tools.Extensions; 12 | global using Microsoft.Extensions.Options; 13 | global using YamlDotNet.Serialization; 14 | global using YamlDotNet.Serialization.NamingConventions; -------------------------------------------------------------------------------- /src/WebSite/wwwroot/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "KnownPro", 3 | "short_name": "KnownPro", 4 | "start_url": "./", 5 | "display": "standalone", 6 | "background_color": "#ffffff", 7 | "theme_color": "#03173d", 8 | "prefer_related_applications": false, 9 | "description": "KnownPro信息管理系统", 10 | "icons": [ 11 | { 12 | "src": "favicon.png", 13 | "type": "image/png", 14 | "sizes": "512x512" 15 | }, 16 | { 17 | "src": "favicon.png", 18 | "type": "image/png", 19 | "sizes": "192x192" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/AntBlazor/AntBlazor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | enable 6 | enable 7 | AntBlazor是实现AntDesign的Blazor静态组件库。 8 | True 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/AntBlazor/Core/InputExtension.cs: -------------------------------------------------------------------------------- 1 | namespace AntBlazor.Core; 2 | 3 | static class InputExtension 4 | { 5 | public static void AddItem(this Dictionary attributes, string key, bool value) 6 | { 7 | if (!value) 8 | return; 9 | 10 | attributes[key] = value; 11 | } 12 | 13 | public static void AddItem(this Dictionary attributes, string key, string value) 14 | { 15 | if (string.IsNullOrWhiteSpace(value)) 16 | return; 17 | 18 | attributes[key] = value; 19 | } 20 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/fold/foldgutter.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-foldmarker { 2 | color: blue; 3 | text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px; 4 | font-family: arial; 5 | line-height: .3; 6 | cursor: pointer; 7 | } 8 | .CodeMirror-foldgutter { 9 | width: .7em; 10 | } 11 | .CodeMirror-foldgutter-open, 12 | .CodeMirror-foldgutter-folded { 13 | cursor: pointer; 14 | } 15 | .CodeMirror-foldgutter-open:after { 16 | content: "\25BE"; 17 | } 18 | .CodeMirror-foldgutter-folded:after { 19 | content: "\25B8"; 20 | } 21 | -------------------------------------------------------------------------------- /src/WebSite/AppWeb.cs: -------------------------------------------------------------------------------- 1 | namespace WebSite; 2 | 3 | static class AppWeb 4 | { 5 | public static void AddApplication(this WebApplicationBuilder builder) 6 | { 7 | builder.Services.AddCodeWF(); 8 | builder.Services.AddKnownCore(info => 9 | { 10 | info.WebRoot = builder.Environment.WebRootPath; 11 | info.ContentRoot = builder.Environment.ContentRootPath; 12 | }); 13 | builder.Services.AddKnownWeb(); 14 | } 15 | 16 | public static void UseApplication(this WebApplication app) 17 | { 18 | app.UseKnown(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/CodeWF/Extensions/MarkdownExtension.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Extensions; 2 | 3 | public static class MarkdownExtension 4 | { 5 | public static string? ToHtml(this string markdown) 6 | { 7 | if (string.IsNullOrWhiteSpace(markdown)) 8 | return default; 9 | 10 | var pipelineBuilder = new MarkdownPipelineBuilder() 11 | .UsePipeTables() 12 | .UseBootstrap(); 13 | pipelineBuilder.UseAdvancedExtensions(); 14 | var pipeline = pipelineBuilder.Build(); 15 | 16 | var html = Markdown.ToHtml(markdown, pipeline); 17 | return html; 18 | } 19 | } -------------------------------------------------------------------------------- /.github/workflows/jekyll-docker.yml: -------------------------------------------------------------------------------- 1 | name: 构建镜像 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: 登录Docker Hub 16 | run: docker login --username=沙漠之狐546477 registry.cn-hangzhou.aliyuncs.com -p ${{ secrets.DOCKER }} 17 | - name: 构建镜像 18 | run: docker build . --file src/WebSite/Dockerfile --tag registry.cn-hangzhou.aliyuncs.com/lequ_co/dotnet9:latest 19 | - name: 推送镜像 20 | run: docker push registry.cn-hangzhou.aliyuncs.com/lequ_co/dotnet9 21 | -------------------------------------------------------------------------------- /src/CodeWF/Extensions/ConstantUtil.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Extensions; 2 | 3 | public static class ConstantUtil 4 | { 5 | public const string DefaultCategory = "default"; 6 | public static string GetBbsCategoryUrl(string slug) => $"/bbs/cat/{slug}"; 7 | public static string GetBbsAlbumUrl(string slug) => $"/bbs/album/{slug}"; 8 | public static string GetBbsPostUrl(BlogPost post) => $"/bbs/post/{post.Date?.Year}/{post.Date?.Month}/{post.Slug}"; 9 | 10 | public static string GetPostGithubPath(string? githubRepository, BlogPost? post) => 11 | $"{githubRepository}/blob/main/{post?.Date?.Year:D4}/{post?.Date?.Month:D2}/{post?.Slug}.md"; 12 | } -------------------------------------------------------------------------------- /src/CodeWF/Options/SiteOption.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Options; 2 | 3 | public class SiteOption 4 | { 5 | public string? AppTitle { get; set; } 6 | public string? Domain { get; set; } 7 | public string? Owner { get; set; } 8 | public string? OwnerDesc { get; set; } 9 | public string? Memo { get; set; } 10 | public string? Favicon { get; set; } 11 | public string? LocalAssetsDir { get; set; } 12 | public string? RemoteAssetsRepository { get; set; } 13 | public int StartYear { get; set; } 14 | public string? BaiAn { get; set; } 15 | public string? WeChatName { get; set; } 16 | public string? WeChatImg { get; set; } 17 | } -------------------------------------------------------------------------------- /src/WebSite/FluentValidations/ConvertIconRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using WebSite.ViewModels; 3 | 4 | namespace WebSite.FluentValidations; 5 | 6 | public class ConvertIconRequestValidator : AbstractValidator 7 | { 8 | public ConvertIconRequestValidator() 9 | { 10 | RuleFor(x => x.SourceImage) 11 | .NotNull().WithMessage("源图像文件不能为空") 12 | .Must(x => x.Length is > 0 and <= 10 * 1024 * 1024).WithMessage("文件大小必须在0到10MB之间"); 13 | 14 | RuleFor(x => x.ConvertSizes) 15 | .NotNull().WithMessage("转换大小数组不能为空") 16 | .Must(x => x.Length > 0).WithMessage("转换大小数组必须包含至少一个元素"); 17 | } 18 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/UPostItem.razor: -------------------------------------------------------------------------------- 1 |
2 |
3 | 11 | @if (!string.IsNullOrWhiteSpace(Post.Cover)) 12 | { 13 |
14 | } 15 |
16 |
17 | 18 | @code { 19 | [Parameter] public BlogPost Post { get; set; } 20 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/dialog/dialog.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-dialog { 2 | position: absolute; 3 | left: 0; right: 0; 4 | background: white; 5 | z-index: 15; 6 | padding: .1em .8em; 7 | overflow: hidden; 8 | color: #333; 9 | } 10 | 11 | .CodeMirror-dialog-top { 12 | border-bottom: 1px solid #eee; 13 | top: 0; 14 | } 15 | 16 | .CodeMirror-dialog-bottom { 17 | border-top: 1px solid #eee; 18 | bottom: 0; 19 | } 20 | 21 | .CodeMirror-dialog input { 22 | border: none; 23 | outline: none; 24 | background: transparent; 25 | width: 20em; 26 | color: inherit; 27 | font-family: monospace; 28 | } 29 | 30 | .CodeMirror-dialog button { 31 | font-size: 70%; 32 | } 33 | -------------------------------------------------------------------------------- /src/WebSite/Shared/SettingBtns.razor.cs: -------------------------------------------------------------------------------- 1 | using CodeWF.Options; 2 | 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace WebSite.Shared 6 | { 7 | public partial class SettingBtns() 8 | { 9 | string? right; 10 | string? bottom; 11 | 12 | string style = string.Empty; 13 | protected override void OnInitialized() 14 | { 15 | base.OnInitialized(); 16 | 17 | if (right != null) 18 | { 19 | style += $"{nameof(right)}:{right}"; 20 | } 21 | 22 | if (bottom != null) 23 | { 24 | style += $"{nameof(bottom)}:{bottom}"; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/AntBlazor/AntTextArea.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 | 5 |
6 | 7 | @code { 8 | [Parameter] public bool Required { get; set; } 9 | [Parameter] public string Value { get; set; } 10 | [Parameter] public string Placeholder { get; set; } 11 | 12 | protected override async Task OnInitializedAsync() 13 | { 14 | await base.OnInitializedAsync(); 15 | InputAttributes.Clear(); 16 | InputAttributes.AddItem("aria-required", Required); 17 | InputAttributes.AddItem("placeholder", Placeholder); 18 | } 19 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/UMenuBar.razor: -------------------------------------------------------------------------------- 1 |
2 | 19 | 20 | @code { 21 | [Parameter] public string Target { get; set; } 22 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntButton.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 | 4 | 5 | @code { 6 | private string ClassName => CssBuilder.Default("ant-btn") 7 | .AddClass($"ant-btn-{Type}") 8 | .AddClass("ant-btn-block", Block) 9 | .AddClass("ant-btn-dangerous", Danger) 10 | .BuildClass(); 11 | 12 | [Parameter] public string Type { get; set; } = "primary"; 13 | [Parameter] public bool Block { get; set; } 14 | [Parameter] public bool Danger { get; set; } 15 | [Parameter] public string OnClick { get; set; } 16 | } -------------------------------------------------------------------------------- /src/CodeWF/CodeWF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | enable 6 | enable 7 | CodeWF是基于Known的内容管理系统前台和后台共用类库。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/AntBlazor/AntFormItem.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 |
5 | @if (!string.IsNullOrWhiteSpace(Label)) 6 | { 7 |
@Label
8 | } 9 |
10 |
11 |
12 | @ChildContent 13 |
14 |
15 |
16 |
17 |
18 | 19 | @code { 20 | [Parameter] public string Label { get; set; } 21 | [Parameter] public RenderFragment ChildContent { get; set; } 22 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntPassword.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 | @if (!string.IsNullOrWhiteSpace(Icon)) 5 | { 6 | 7 | } 8 | 9 |
10 | 11 | @code { 12 | [Parameter] public bool Required { get; set; } 13 | [Parameter] public string Icon { get; set; } 14 | [Parameter] public string Placeholder { get; set; } 15 | 16 | protected override async Task OnInitializedAsync() 17 | { 18 | await base.OnInitializedAsync(); 19 | InputAttributes.Clear(); 20 | InputAttributes.AddItem("aria-required", Required); 21 | InputAttributes.AddItem("placeholder", Placeholder); 22 | } 23 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/CmsCard.razor: -------------------------------------------------------------------------------- 1 |
2 | @if (!string.IsNullOrWhiteSpace(Title)) 3 | { 4 |
5 | 6 |
7 | } 8 | else if (HeadTemplate != null) 9 | { 10 |
11 | @HeadTemplate 12 |
13 | } 14 |
15 | @ChildContent 16 |
17 |
18 | 19 | @code { 20 | [Parameter] public string Class { get; set; } 21 | [Parameter] public string Icon { get; set; } 22 | [Parameter] public string Title { get; set; } 23 | [Parameter] public RenderFragment HeadTemplate { get; set; } 24 | [Parameter] public RenderFragment ChildContent { get; set; } 25 | } -------------------------------------------------------------------------------- /src/WebSite/Routes.razor: -------------------------------------------------------------------------------- 1 | @using Known.Components 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

页面不存在!

12 |
13 |
14 |
15 | 16 | @code { 17 | [Inject] private UIContext Context { get; set; } 18 | [CascadingParameter] private HttpContext HttpContext { get; set; } 19 | 20 | protected override async Task OnInitializedAsync() 21 | { 22 | await base.OnInitializedAsync(); 23 | HttpContext.SetContext(Context); 24 | } 25 | } -------------------------------------------------------------------------------- /src/WebSite/Shared/MediaBox.razor: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 | @Title 8 |
9 |

@ChildContent

10 |
11 |
12 | 13 | @code { 14 | [Parameter] public string Style { get; set; } 15 | [Parameter] public string Icon { get; set; } 16 | [Parameter] public string Title { get; set; } 17 | [Parameter] public string Link { get; set; } 18 | [Parameter] public int AnimationDelay { get; set; } 19 | [Parameter] public RenderFragment ChildContent { get; set; } 20 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntTag.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 | @if (IsColor) 4 | { 5 | @ChildContent 6 | } 7 | else 8 | { 9 | @ChildContent 10 | } 11 | 12 | @code { 13 | [Parameter] public string Color { get; set; } 14 | [Parameter] public string OnClick { get; set; } 15 | [Parameter] public RenderFragment ChildContent { get; set; } 16 | 17 | protected override async Task OnInitializedAsync() 18 | { 19 | await base.OnInitializedAsync(); 20 | InputAttributes.Clear(); 21 | InputAttributes.AddItem("onclick", OnClick); 22 | } 23 | 24 | private bool IsColor => Color.StartsWith("#") || Color.StartsWith("rgb("); 25 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntModal.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 | 19 | 20 | @code { 21 | [Parameter] public int Width { get; set; } 22 | [Parameter] public RenderFragment ChildContent { get; set; } 23 | } -------------------------------------------------------------------------------- /src/WebSite/Assets/site/category.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Sort": 10, 4 | "Name": ".NET", 5 | "Memo": ".NET相关文章", 6 | "Slug": "dotnet" 7 | }, 8 | { 9 | "Sort": 11, 10 | "Name": "Python", 11 | "Memo": "Python相关文章", 12 | "Slug": "python" 13 | }, 14 | { 15 | "Sort": 20, 16 | "Name": "前端", 17 | "Memo": "前端相关文章", 18 | "Slug": "frontend" 19 | }, 20 | { 21 | "Sort": 30, 22 | "Name": "数据库", 23 | "Memo": "数据库相关文章", 24 | "Slug": "database" 25 | }, 26 | { 27 | "Sort": 40, 28 | "Name": "更多语言", 29 | "Memo": "其他语言相关文章", 30 | "Slug": "morelanguage" 31 | }, 32 | { 33 | "Sort": 50, 34 | "Name": "课程", 35 | "Memo": "站长推荐", 36 | "Slug": "course" 37 | }, 38 | { 39 | "Sort": 60, 40 | "Name": "分享", 41 | "Memo": "站长推荐文章或工具或在项目", 42 | "Slug": "share" 43 | } 44 | ] -------------------------------------------------------------------------------- /src/CodeWF/Shared/UPostCount.razor: -------------------------------------------------------------------------------- 1 | @inject IOptions SiteOption 2 |
3 | @if (Post?.Lastmod != null) 4 | { 5 | 更新于@(Post?.Lastmod?.ToString("yyyy-MM-dd HH:mm:ss")) 6 | } 7 | else 8 | { 9 | 创建于@(Post?.Date?.ToString("yyyy-MM-dd HH:mm:ss")) 10 | } 11 | | 12 | @(string.IsNullOrWhiteSpace(Post?.Author) ? SiteOption.Value.Owner : Post!.Author) 13 | @if (ShowEdit) 14 | { 15 | | 16 | 我要编辑、留言 17 | } 18 |
19 | 20 | @code { 21 | [Parameter] public BlogPost Post { get; set; } 22 | [Parameter] public bool ShowEdit { get; set; } = true; 23 | } -------------------------------------------------------------------------------- /src/CodeWF/Pages/Bbs/UWebSiteCount.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 5 | @if (_websiteCount is not { Count: > 0 }) 6 | { 7 | 8 | } 9 | else 10 | { 11 | var index = 0; 12 | foreach (var item in _websiteCount) 13 | { 14 | index++; 15 |
16 |
@item.Key
17 |
@item.Value
18 |
19 | } 20 | } 21 |
22 | 23 | @code { 24 | private Dictionary? _websiteCount; 25 | 26 | protected override async Task OnInitAsync() 27 | { 28 | await base.OnInitAsync(); 29 | _websiteCount = await AppService.GetWebSiteCountAsync(); 30 | } 31 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/hint/show-hint.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-hints { 2 | position: absolute; 3 | z-index: 10; 4 | overflow: hidden; 5 | list-style: none; 6 | 7 | margin: 0; 8 | padding: 2px; 9 | 10 | -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); 11 | -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); 12 | box-shadow: 2px 3px 5px rgba(0,0,0,.2); 13 | border-radius: 3px; 14 | border: 1px solid silver; 15 | 16 | background: white; 17 | font-size: 90%; 18 | font-family: monospace; 19 | 20 | max-height: 20em; 21 | overflow-y: auto; 22 | } 23 | 24 | .CodeMirror-hint { 25 | margin: 0; 26 | padding: 0 4px; 27 | border-radius: 2px; 28 | max-width: 19em; 29 | overflow: hidden; 30 | white-space: pre; 31 | color: black; 32 | cursor: pointer; 33 | } 34 | 35 | li.CodeMirror-hint-active { 36 | background: #08f; 37 | color: white; 38 | } 39 | -------------------------------------------------------------------------------- /src/AntBlazor/AntInput.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 | @if (!string.IsNullOrWhiteSpace(Icon)) 5 | { 6 | 7 | } 8 | 9 |
10 | 11 | @code { 12 | [Parameter] public bool Required { get; set; } 13 | [Parameter] public string Type { get; set; } = "text"; 14 | [Parameter] public string Icon { get; set; } 15 | [Parameter] public string Value { get; set; } 16 | [Parameter] public string Placeholder { get; set; } 17 | 18 | protected override async Task OnInitializedAsync() 19 | { 20 | await base.OnInitializedAsync(); 21 | InputAttributes.Clear(); 22 | InputAttributes.AddItem("value", Value); 23 | InputAttributes.AddItem("aria-required", Required); 24 | InputAttributes.AddItem("placeholder", Placeholder); 25 | } 26 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/UPostRank.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 5 | @if (_posts is not { Count: > 0 }) 6 | { 7 | 8 | } 9 | else 10 | { 11 | var index = 0; 12 | foreach (var item in _posts) 13 | { 14 | index++; 15 |
16 |
@index
17 |
18 | @item.Title 19 |
20 |
21 | } 22 | } 23 |
24 | 25 | @code { 26 | private List? _posts; 27 | 28 | protected override async Task OnInitAsync() 29 | { 30 | await base.OnInitAsync(); 31 | _posts = await AppService.GetBannerPostAsync(); 32 | } 33 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/mode/multiplex_test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function() { 5 | CodeMirror.defineMode("markdown_with_stex", function(){ 6 | var inner = CodeMirror.getMode({}, "stex"); 7 | var outer = CodeMirror.getMode({}, "markdown"); 8 | 9 | var innerOptions = { 10 | open: '$', 11 | close: '$', 12 | mode: inner, 13 | delimStyle: 'delim', 14 | innerStyle: 'inner' 15 | }; 16 | 17 | return CodeMirror.multiplexingMode(outer, innerOptions); 18 | }); 19 | 20 | var mode = CodeMirror.getMode({}, "markdown_with_stex"); 21 | 22 | function MT(name) { 23 | test.mode( 24 | name, 25 | mode, 26 | Array.prototype.slice.call(arguments, 1), 27 | 'multiplexing'); 28 | } 29 | 30 | MT( 31 | "stexInsideMarkdown", 32 | "[strong **Equation:**] [delim $][inner&tag \\pi][delim $]"); 33 | })(); 34 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/lint/yaml-lint.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | // Depends on js-yaml.js from https://github.com/nodeca/js-yaml 15 | 16 | // declare global: jsyaml 17 | 18 | CodeMirror.registerHelper("lint", "yaml", function(text) { 19 | var found = []; 20 | try { jsyaml.load(text); } 21 | catch(e) { 22 | var loc = e.mark; 23 | found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message }); 24 | } 25 | return found; 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /src/WebSite/Shared/FriendLink.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 22 | 23 | @code { 24 | private List? _links; 25 | 26 | protected override async Task OnInitAsync() 27 | { 28 | await base.OnInitAsync(); 29 | 30 | _links = await AppService.GetAllFriendLinkItemsAsync(); 31 | } 32 | } -------------------------------------------------------------------------------- /src/WebSite/wwwroot/js/settings.js: -------------------------------------------------------------------------------- 1 | class Settings 2 | { 3 | constructor() 4 | { 5 | this.defaultTimeout = 1500; 6 | } 7 | 8 | taskCompleted(btn, timeout) 9 | { 10 | if (btn) 11 | { 12 | btn.classList.add("checked"); 13 | setTimeout(() => btn.classList.remove("checked"), timeout ?? this.defaultTimeout); 14 | } 15 | } 16 | 17 | openBtns(containerid) 18 | { 19 | const container = document.getElementById(containerid); 20 | container.classList.toggle("open"); 21 | } 22 | 23 | goBack() 24 | { 25 | window.history.back(); 26 | } 27 | 28 | goToTop() 29 | { 30 | window.scrollTo({ 31 | top: 0, 32 | left: 0, 33 | behavior: "smooth" 34 | }); 35 | } 36 | 37 | goToBottom() 38 | { 39 | window.scrollTo({ 40 | top: document.body.scrollHeight, 41 | left: 0, 42 | behavior: "smooth" 43 | }); 44 | } 45 | } -------------------------------------------------------------------------------- /src/WebSite/Jobs/FileCleanerJob.cs: -------------------------------------------------------------------------------- 1 | using Quartz; 2 | 3 | namespace WebSite.Jobs; 4 | 5 | public class FileCleanerJob(IWebHostEnvironment env) : IJob 6 | { 7 | public Task Execute(IJobExecutionContext context) 8 | { 9 | var directoryPath = Path.Combine(env.WebRootPath, "IconFolder"); 10 | if (!Directory.Exists(directoryPath)) 11 | { 12 | return Task.CompletedTask; 13 | } 14 | try 15 | { 16 | var files = Directory.GetFiles(directoryPath); 17 | foreach (var file in files) 18 | { 19 | var creationTime = File.GetCreationTime(file); 20 | if ((DateTime.Now - creationTime).TotalMinutes > 2) 21 | { 22 | File.Delete(file); 23 | } 24 | } 25 | } 26 | catch (Exception ex) 27 | { 28 | // Handle exceptions, e.g., log them 29 | Console.WriteLine($"Error: {ex.Message}"); 30 | } 31 | 32 | return Task.CompletedTask; 33 | } 34 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntAlert.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 |
@ChildContent
5 | @if (Closable) 6 | { 7 | 10 | } 11 |
12 | 13 | @code { 14 | [Parameter] public string Type { get; set; } 15 | [Parameter] public bool Closable { get; set; } 16 | [Parameter] public RenderFragment ChildContent { get; set; } 17 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/fonts/editormd-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/WebSite/Dockerfile: -------------------------------------------------------------------------------- 1 | # 请参阅 https://aka.ms/customizecontainer 以了解如何自定义调试容器,以及 Visual Studio 如何使用此 Dockerfile 生成映像以更快地进行调试。 2 | 3 | # 此阶段用于在快速模式(默认为调试配置)下从 VS 运行时 4 | FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base 5 | USER root 6 | WORKDIR /app 7 | EXPOSE 8080 8 | EXPOSE 8081 9 | 10 | 11 | # 此阶段用于生成服务项目 12 | FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build 13 | ARG BUILD_CONFIGURATION=Release 14 | WORKDIR /src 15 | COPY ["src/WebSite/WebSite.csproj", "src/WebSite/"] 16 | COPY ["src/CodeWF/CodeWF.csproj", "src/CodeWF/"] 17 | COPY ["src/AntBlazor/AntBlazor.csproj", "src/AntBlazor/"] 18 | RUN dotnet restore "./src/WebSite/WebSite.csproj" 19 | COPY . . 20 | WORKDIR "/src/src/WebSite" 21 | RUN dotnet build "./WebSite.csproj" -c $BUILD_CONFIGURATION -o /app/build 22 | 23 | # 此阶段用于发布要复制到最终阶段的服务项目 24 | FROM build AS publish 25 | ARG BUILD_CONFIGURATION=Release 26 | RUN dotnet publish "./WebSite.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 27 | 28 | # 此阶段在生产中使用,或在常规模式下从 VS 运行时使用(在不使用调试配置时为默认值) 29 | FROM base AS final 30 | WORKDIR /app 31 | COPY --from=publish /app/publish . 32 | ENTRYPOINT ["dotnet", "WebSite.dll"] -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/lint/json-lint.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | // Depends on jsonlint.js from https://github.com/zaach/jsonlint 5 | 6 | // declare global: jsonlint 7 | 8 | (function(mod) { 9 | if (typeof exports == "object" && typeof module == "object") // CommonJS 10 | mod(require("../../lib/codemirror")); 11 | else if (typeof define == "function" && define.amd) // AMD 12 | define(["../../lib/codemirror"], mod); 13 | else // Plain browser env 14 | mod(CodeMirror); 15 | })(function(CodeMirror) { 16 | "use strict"; 17 | 18 | CodeMirror.registerHelper("lint", "json", function(text) { 19 | var found = []; 20 | jsonlint.parseError = function(str, hash) { 21 | var loc = hash.loc; 22 | found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column), 23 | to: CodeMirror.Pos(loc.last_line - 1, loc.last_column), 24 | message: str}); 25 | }; 26 | try { jsonlint.parse(text); } 27 | catch(e) {} 28 | return found; 29 | }); 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /src/WebSite/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | "WxGZHId": "", 11 | "WxAppId": "", 12 | "WxAppSecret": "", 13 | "WxRedirectUri": "", 14 | "Site": { 15 | "AppTitle": "码坊", 16 | "Domain": "https://dotnet9.com", 17 | "Memo": "码坊是使用.NET 10 Blazor开发的一个网站,这里有技术文章,有开源项目介绍,有在线工具使用: 码坊—文章启智,工具助力", 18 | "Owner": "沙漠尽头的狼", 19 | "OwnerDesc": "从事Dotnet开发10年+,此站目的分享以Dotnet为主的技术类文章,以此平台与更多的程序员朋友技术交流,祝愿Dotnet社区发展渐好。", 20 | "favicon": "https://img1.dotnet9.com/site/favicon/logo.png", 21 | "LocalAssetsDir": "D:\\github\\owner\\Assets.Dotnet9", 22 | "RemoteAssetsRepository": "https://github.com/dotnet9/Assets.Dotnet9", 23 | "StartYear": 2019, 24 | "BaiAn": "备案号", 25 | "WeChatName": "Dotnet9", 26 | "WeChatImg": "https://img1.dotnet9.com/site/favicon/wechatpublic.jpg" 27 | }, 28 | "OpenAI": { 29 | "Key": "your key", 30 | "Endpoint": "https://open.bigmodel.cn/api/paas/v4/", 31 | "ChatModel": "glm-4-flash" 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Dotnet9(dotnet9.com) 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. 22 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/edit/trailingspace.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { 13 | if (prev == CodeMirror.Init) prev = false; 14 | if (prev && !val) 15 | cm.removeOverlay("trailingspace"); 16 | else if (!prev && val) 17 | cm.addOverlay({ 18 | token: function(stream) { 19 | for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} 20 | if (i > stream.pos) { stream.pos = i; return null; } 21 | stream.pos = l; 22 | return "trailingspace"; 23 | }, 24 | name: "trailingspace" 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/CodeWF/Pages/Bbs/AlbumList.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 5 | @if (_albums != null && _albums.Count > 0) 6 | { 7 | foreach (var item in _albums) 8 | { 9 | 10 | @* *@ 11 | @item.Name 12 | 13 | } 14 | } 15 | 16 | 17 | @code { 18 | private List _albums = []; 19 | 20 | protected override async Task OnInitAsync() 21 | { 22 | await base.OnInitAsync(); 23 | var lists = await AppService.GetAllAlbumItemsAsync(); 24 | _albums = lists?.OrderBy(c => c.Sort).ToList(); 25 | } 26 | 27 | 28 | private bool IsActive(string code) 29 | { 30 | var uri = Navigation.Uri.Split('?')[0]; 31 | code = code.ToLower(); 32 | if (code == "" && uri.EndsWith("/bbs")) 33 | return true; 34 | 35 | return uri.EndsWith($"/{code}"); 36 | } 37 | } -------------------------------------------------------------------------------- /src/CodeWF/Pages/Bbs/CategoryList.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 5 | @if (_categories is { Count: > 0 }) 6 | { 7 | foreach (var item in _categories) 8 | { 9 | 10 | @* *@ 11 | @item.Name 12 | 13 | } 14 | } 15 | 16 | 17 | @code { 18 | private List _categories = []; 19 | 20 | protected override async Task OnInitAsync() 21 | { 22 | await base.OnInitAsync(); 23 | var lists = await AppService.GetAllCategoryItemsAsync(); 24 | _categories = lists?.OrderBy(c => c.Sort).ToList(); 25 | } 26 | 27 | 28 | private bool IsActive(string code) 29 | { 30 | var uri = Navigation.Uri.Split('?')[0]; 31 | code = code.ToLower(); 32 | if (code == "" && uri.EndsWith("/bbs")) 33 | return true; 34 | 35 | return uri.EndsWith($"/{code}"); 36 | } 37 | } -------------------------------------------------------------------------------- /src/WebSite/Controllers/WebController.cs: -------------------------------------------------------------------------------- 1 | using CodeWF.Options; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Options; 5 | using System.Net.Mime; 6 | 7 | namespace WebSite.Controllers; 8 | 9 | [ApiController] 10 | public class WebController(IOptions siteOption, AppService appService) : ControllerBase 11 | { 12 | const string ContentType = "application/xml"; 13 | 14 | [Route("/rss")] 15 | [AllowAnonymous] 16 | public async Task GetRssAsync() 17 | { 18 | var rss = await appService.GetRssAsync(); 19 | 20 | return Content(rss, ContentType); 21 | } 22 | 23 | [Route("/sitemap.xml")] 24 | [AllowAnonymous] 25 | public async Task GetSiteMapAsync() 26 | { 27 | const string cacheKey = "sitemap.xml"; 28 | ContentDisposition cd = new() 29 | { 30 | FileName = cacheKey, 31 | Inline = true 32 | }; 33 | Response.Headers.Append("Content-Disposition", cd.ToString()); 34 | var rss = await appService.GetSiteMapAsync(); 35 | 36 | return Content(rss, ContentType); 37 | } 38 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntEmpty.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

暂无数据

16 | 17 |
18 | 19 | @code { 20 | 21 | } -------------------------------------------------------------------------------- /src/AntBlazor/Core/BaseComponent.cs: -------------------------------------------------------------------------------- 1 | namespace AntBlazor.Core; 2 | 3 | /// 4 | /// 抽象组件基类。 5 | /// 6 | public abstract class BaseComponent : ComponentBase 7 | { 8 | /// 9 | /// 取得或设置组件ID。 10 | /// 11 | [Parameter] public string Id { get; set; } 12 | 13 | /// 14 | /// 取得或设置组件名称。 15 | /// 16 | [Parameter] public string Name { get; set; } 17 | 18 | /// 19 | /// 取得或设置组件是否只读。 20 | /// 21 | [Parameter] public bool ReadOnly { get; set; } 22 | 23 | /// 24 | /// 取得或设置组件是否可用,默认可用。 25 | /// 26 | [Parameter] public bool Enabled { get; set; } = true; 27 | 28 | /// 29 | /// 取得或设置组件是否可见,默认可见。 30 | /// 31 | [Parameter] public bool Visible { get; set; } = true; 32 | 33 | /// 34 | /// 取得或设置JS运行时实例。 35 | /// 36 | [Inject] public IJSRuntime JSRuntime { get; set; } 37 | 38 | /// 39 | /// 取得或设置注入的导航管理者实例。 40 | /// 41 | [Inject] public NavigationManager Navigation { get; set; } 42 | 43 | internal Dictionary InputAttributes { get; } = []; 44 | } -------------------------------------------------------------------------------- /src/CodeWF/Models/BlogPost.cs: -------------------------------------------------------------------------------- 1 | namespace CodeWF.Models; 2 | 3 | public class BlogPostBrief 4 | { 5 | public string? Title { get; set; } 6 | public string? Slug { get; set; } 7 | public string? Description { get; set; } 8 | public DateTime? Date { get; set; } 9 | public DateTime? Lastmod { get; set; } 10 | public string? Copyright { get; set; } 11 | public bool Banner { get; set; } 12 | public string? Author { get; set; } 13 | public string? LastModifyUser { get; set; } 14 | public string? OriginalTitle { get; set; } 15 | public string? OriginalLink { get; set; } 16 | public bool Draft { get; set; } 17 | public string? Cover { get; set; } 18 | public List? Albums { get; set; } 19 | public List? Categories { get; set; } 20 | public List? Tags { get; set; } 21 | } 22 | 23 | public class BlogPost : BlogPostBrief 24 | { 25 | public string? Content { get; set; } 26 | public string? HtmlContent { get; set; } 27 | } 28 | 29 | public class CopyRights 30 | { 31 | public const string Reprinted = nameof(Reprinted); 32 | public const string Contributes = nameof(Contributes); 33 | public const string Original = nameof(Original); 34 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/js/toc.js: -------------------------------------------------------------------------------- 1 | window.getTOC = function getTOC(id) { 2 | let hlevel = "h1, h2, h3, h4"; 3 | var titles = $("#" + id) 4 | .find(hlevel) 5 | .map(function () { 6 | return { type: this.tagName.toLowerCase(), id: $(this).prop("id"), title: $(this).text() }; 7 | }) 8 | .get(); 9 | 10 | const currentUrl = window.location.href.split("#")[0]; 11 | titles.forEach(function (item) { 12 | const link = `${item.title}`; 13 | const wrappedLink = `
${link}
`; 14 | $("#toc").append(wrappedLink); 15 | }); 16 | 17 | $(window).scroll(function (){ 18 | $("#toc").toggleClass('toc-show', $(this).scrollTop() > 400); 19 | }); 20 | tocUp(200); 21 | }; 22 | 23 | function tocUp(val) { 24 | // 平滑滚动到对应位置 25 | $("body").on("click", "#toc a", function (event) { 26 | event.preventDefault(); // 阻止默认链接行为 27 | const targetId = $(this).attr("href").split("#")[1]; 28 | const targetElement = $(`#${targetId}`); 29 | 30 | if (targetElement.length) { 31 | const offset = targetElement.offset().top - val; 32 | $("html, body").animate({ scrollTop: offset }, 1200); // 平滑滚动 33 | } 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /src/WebSite/wwwroot/css/vendor/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v1.0.0 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */nav[data-toggle=toc] .nav>li>a{display:block;padding:4px 20px;font-size:15px;font-weight:500;color:#767676}nav[data-toggle=toc] .nav>li>a:focus,nav[data-toggle=toc] .nav>li>a:hover{padding-left:19px;color:#563d7c;text-decoration:none;background-color:transparent;border-left:1px solid #563d7c}nav[data-toggle=toc] .nav-link.active,nav[data-toggle=toc] .nav-link.active:focus,nav[data-toggle=toc] .nav-link.active:hover{padding-left:18px;font-weight:700;color:#563d7c;background-color:transparent;border-left:2px solid #563d7c}nav[data-toggle=toc] .nav-link+ul{display:none;padding-bottom:10px}nav[data-toggle=toc] .nav .nav>li>a{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:14px;font-weight:400}nav[data-toggle=toc] .nav .nav>li>a:focus,nav[data-toggle=toc] .nav .nav>li>a:hover{padding-left:29px}nav[data-toggle=toc] .nav .nav>li>.active,nav[data-toggle=toc] .nav .nav>li>.active:focus,nav[data-toggle=toc] .nav .nav>li>.active:hover{padding-left:28px;font-weight:500}nav[data-toggle=toc] .nav-link.active+ul{display:block} -------------------------------------------------------------------------------- /src/CodeWF/Pages/Docs/Document.razor: -------------------------------------------------------------------------------- 1 | @page "/doc" 2 | @page "/doc/{slug}" 3 | 4 | @inherits BaseComponent 5 | @inject IOptions SiteOptions 6 | @inject AppService AppService 7 | 8 | @model?.Name - @SiteOptions.Value.AppTitle 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | @if (!string.IsNullOrWhiteSpace(model?.Repository)) 17 | { 18 |
19 | 20 | 看看Github上的源码 21 |
22 | } 23 |
24 | 25 | 26 | 27 |
28 |
29 | 30 | @code { 31 | private DocItem? model; 32 | 33 | [Parameter] public string? Slug { get; set; } 34 | 35 | protected override async Task OnInitAsync() 36 | { 37 | await base.OnInitAsync(); 38 | 39 | model = await AppService.GetDocItemAsync(Slug); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/CodeWF/AppConfig.cs: -------------------------------------------------------------------------------- 1 | using Known.Components; 2 | 3 | namespace CodeWF; 4 | 5 | public static class AppConfig 6 | { 7 | public static string AppId => "CodeWF"; 8 | 9 | public static string AppName => "码坊"; 10 | 11 | public static void AddCodeWF(this IServiceCollection services) 12 | { 13 | Console.WriteLine(AppName); 14 | 15 | var assembly = typeof(AppConfig).Assembly; 16 | 17 | services.AddKnown(info => 18 | { 19 | info.Id = AppId; 20 | info.Name = AppName; 21 | info.IsSize = true; 22 | info.IsLanguage = true; 23 | info.IsTheme = true; 24 | info.Assembly = assembly; 25 | }); 26 | 27 | //添加样式 28 | KStyleSheet.AddStyle("_content/AntBlazor/css/ant-design-blazor.css"); 29 | KStyleSheet.AddStyle("_content/AntBlazor/css/web.css"); 30 | KStyleSheet.AddStyle("_content/CodeWF/css/editormd.css"); 31 | KStyleSheet.AddStyle("_content/CodeWF/css/toc.css"); 32 | KStyleSheet.AddStyle("_content/CodeWF/css/web.css"); 33 | 34 | //添加脚本 35 | KScript.AddScript("_content/AntBlazor/js/AntBlazor.js"); 36 | KScript.AddScript("_content/CodeWF/js/editormd.js"); 37 | 38 | Config.AddModule(assembly); 39 | } 40 | } -------------------------------------------------------------------------------- /src/WebSite/WebSite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | enable 6 | enable 7 | 267d663b-ea50-422e-b9fd-758356e11900 8 | Linux 9 | ..\.. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/lint/css-lint.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | // Depends on csslint.js from https://github.com/stubbornella/csslint 5 | 6 | // declare global: CSSLint 7 | 8 | (function(mod) { 9 | if (typeof exports == "object" && typeof module == "object") // CommonJS 10 | mod(require("../../lib/codemirror")); 11 | else if (typeof define == "function" && define.amd) // AMD 12 | define(["../../lib/codemirror"], mod); 13 | else // Plain browser env 14 | mod(CodeMirror); 15 | })(function(CodeMirror) { 16 | "use strict"; 17 | 18 | CodeMirror.registerHelper("lint", "css", function(text) { 19 | var found = []; 20 | if (!window.CSSLint) return found; 21 | var results = CSSLint.verify(text), messages = results.messages, message = null; 22 | for ( var i = 0; i < messages.length; i++) { 23 | message = messages[i]; 24 | var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col; 25 | found.push({ 26 | from: CodeMirror.Pos(startLine, startCol), 27 | to: CodeMirror.Pos(endLine, endCol), 28 | message: message.message, 29 | severity : message.type 30 | }); 31 | } 32 | return found; 33 | }); 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /src/WebSite/wwwroot/css/responsive-helpers.css: -------------------------------------------------------------------------------- 1 | /* 创建新的响应式辅助类CSS文件 */ 2 | .gap-1 { gap: 0.25rem; } 3 | .gap-2 { gap: 0.5rem; } 4 | .gap-3 { gap: 1rem; } 5 | .gap-4 { gap: 1.5rem; } 6 | .gap-5 { gap: 3rem; } 7 | 8 | /* 响应式间距 */ 9 | @media (max-width: 576px) { 10 | .mb-sm-0 { margin-bottom: 0 !important; } 11 | .mb-sm-1 { margin-bottom: 0.25rem !important; } 12 | .mb-sm-2 { margin-bottom: 0.5rem !important; } 13 | .mb-sm-3 { margin-bottom: 1rem !important; } 14 | .mb-sm-4 { margin-bottom: 1.5rem !important; } 15 | .mb-sm-5 { margin-bottom: 3rem !important; } 16 | 17 | .mt-sm-0 { margin-top: 0 !important; } 18 | .mt-sm-1 { margin-top: 0.25rem !important; } 19 | .mt-sm-2 { margin-top: 0.5rem !important; } 20 | .mt-sm-3 { margin-top: 1rem !important; } 21 | .mt-sm-4 { margin-top: 1.5rem !important; } 22 | .mt-sm-5 { margin-top: 3rem !important; } 23 | } 24 | 25 | /* 响应式文本对齐 */ 26 | @media (max-width: 576px) { 27 | .text-sm-center { text-align: center !important; } 28 | .text-sm-left { text-align: left !important; } 29 | .text-sm-right { text-align: right !important; } 30 | } 31 | 32 | /* 响应式显示/隐藏 */ 33 | @media (max-width: 576px) { 34 | .d-sm-none { display: none !important; } 35 | .d-sm-block { display: block !important; } 36 | .d-sm-flex { display: flex !important; } 37 | } -------------------------------------------------------------------------------- /src/WebSite/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* 添加到您现有的CSS文件中 */ 2 | .responsive-container { 3 | padding: 2rem 1rem; 4 | } 5 | 6 | @media (min-width: 768px) { 7 | .responsive-container { 8 | padding: 3rem 2rem; 9 | } 10 | } 11 | 12 | /* 改进卡片样式 */ 13 | .card-enhanced { 14 | border-radius: 8px; 15 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 16 | transition: transform 0.3s ease, box-shadow 0.3s ease; 17 | } 18 | 19 | .card-enhanced:hover { 20 | transform: translateY(-5px); 21 | box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1); 22 | } 23 | 24 | /* 改进导航栏样式 */ 25 | .topnav.navbar { 26 | transition: background-color 0.3s ease, box-shadow 0.3s ease; 27 | } 28 | 29 | /* 改进Logo样式 */ 30 | .logo-container { 31 | display: flex; 32 | align-items: center; 33 | transition: transform 0.2s ease; 34 | } 35 | 36 | .logo-container:hover { 37 | transform: scale(1.05); 38 | } 39 | 40 | .logo-image { 41 | margin-right: 0.5rem; 42 | } 43 | 44 | /* 改进友情链接样式 */ 45 | .links { 46 | display: flex; 47 | flex-wrap: wrap; 48 | align-items: center; 49 | gap: 1rem; 50 | } 51 | 52 | .links a { 53 | padding: 0.25rem 0.5rem; 54 | border-radius: 4px; 55 | transition: background-color 0.2s ease; 56 | } 57 | 58 | .links a:hover { 59 | background-color: rgba(0, 0, 0, 0.05); 60 | text-decoration: none; 61 | } -------------------------------------------------------------------------------- /src/WebSite/wwwroot/css/animations.css: -------------------------------------------------------------------------------- 1 | /* 创建新的动画CSS文件 */ 2 | .fade-in { 3 | animation: fadeIn 0.5s ease-in; 4 | } 5 | 6 | @keyframes fadeIn { 7 | from { opacity: 0; } 8 | to { opacity: 1; } 9 | } 10 | 11 | .slide-up { 12 | animation: slideUp 0.5s ease-out; 13 | } 14 | 15 | @keyframes slideUp { 16 | from { transform: translateY(20px); opacity: 0; } 17 | to { transform: translateY(0); opacity: 1; } 18 | } 19 | 20 | .pulse { 21 | animation: pulse 2s infinite; 22 | } 23 | 24 | @keyframes pulse { 25 | 0% { transform: scale(1); } 26 | 50% { transform: scale(1.05); } 27 | 100% { transform: scale(1); } 28 | } 29 | 30 | /* 悬停效果 */ 31 | .hover-lift { 32 | transition: transform 0.3s ease; 33 | } 34 | 35 | .hover-lift:hover { 36 | transform: translateY(-5px); 37 | } 38 | 39 | /* 按钮动画 */ 40 | .btn-animated { 41 | position: relative; 42 | overflow: hidden; 43 | z-index: 1; 44 | } 45 | 46 | .btn-animated:after { 47 | content: ''; 48 | position: absolute; 49 | bottom: 0; 50 | left: 0; 51 | width: 100%; 52 | height: 100%; 53 | background-color: rgba(255, 255, 255, 0.2); 54 | transform: scaleX(0); 55 | transform-origin: right; 56 | transition: transform 0.3s ease; 57 | z-index: -1; 58 | } 59 | 60 | .btn-animated:hover:after { 61 | transform: scaleX(1); 62 | transform-origin: left; 63 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntResult.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 |
5 | 6 | 7 | 8 |
9 | @if (!string.IsNullOrWhiteSpace(Title)) 10 | { 11 |
@Title
12 | } 13 | @if (!string.IsNullOrWhiteSpace(SubTitle)) 14 | { 15 |
@SubTitle
16 | } 17 | @if (ExtraContent != null) 18 | { 19 |
20 | @ExtraContent 21 |
22 | } 23 |
24 | 25 | @code { 26 | [Parameter] public string Type { get; set; } 27 | [Parameter] public string Title { get; set; } 28 | [Parameter] public string SubTitle { get; set; } 29 | [Parameter] public RenderFragment ExtraContent { get; set; } 30 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntRadio.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 |
4 | @if (Items != null && Items.Count > 0) 5 | { 6 | var index = 0; 7 | foreach (var item in Items) 8 | { 9 | var classWrapper = "ant-radio-wrapper"; 10 | var className = "ant-radio"; 11 | if (item.Key == Value) 12 | { 13 | classWrapper += " ant-radio-wrapper-checked"; 14 | className += " ant-radio-checked"; 15 | } 16 | 30 | } 31 | } 32 |
33 | 34 | @code { 35 | [Parameter] public string Value { get; set; } 36 | [Parameter] public Dictionary Items { get; set; } 37 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/jquery.flowchart.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery.flowchart.js v1.1.0 | jquery.flowchart.min.js | jQuery plugin for flowchart.js. | MIT License | By: Pandao | https://github.com/pandao/jquery.flowchart.js | 2015-03-09 */ 2 | (function(factory){if(typeof require==="function"&&typeof exports==="object"&&typeof module==="object"){module.exports=factory}else{if(typeof define==="function"){factory(jQuery,flowchart)}else{factory($,flowchart)}}}(function(jQuery,flowchart){(function($){$.fn.flowChart=function(options){options=options||{};var defaults={"x":0,"y":0,"line-width":2,"line-length":50,"text-margin":10,"font-size":14,"font-color":"black","line-color":"black","element-color":"black","fill":"white","yes-text":"yes","no-text":"no","arrow-end":"block","symbols":{"start":{"font-color":"black","element-color":"black","fill":"white"},"end":{"class":"end-element"}},"flowstate":{"past":{"fill":"#CCCCCC","font-size":12},"current":{"fill":"black","font-color":"white","font-weight":"bold"},"future":{"fill":"white"},"request":{"fill":"blue"},"invalid":{"fill":"#444444"},"approved":{"fill":"#58C4A3","font-size":12,"yes-text":"APPROVED","no-text":"n/a"},"rejected":{"fill":"#C45879","font-size":12,"yes-text":"n/a","no-text":"REJECTED"}}};return this.each(function(){var $this=$(this);var diagram=flowchart.parse($this.text());var settings=$.extend(true,defaults,options);$this.html("");diagram.drawSVG(this,settings)})}})(jQuery)})); -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/tern/worker.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | // declare global: tern, server 5 | 6 | var server; 7 | 8 | this.onmessage = function(e) { 9 | var data = e.data; 10 | switch (data.type) { 11 | case "init": return startServer(data.defs, data.plugins, data.scripts); 12 | case "add": return server.addFile(data.name, data.text); 13 | case "del": return server.delFile(data.name); 14 | case "req": return server.request(data.body, function(err, reqData) { 15 | postMessage({id: data.id, body: reqData, err: err && String(err)}); 16 | }); 17 | case "getFile": 18 | var c = pending[data.id]; 19 | delete pending[data.id]; 20 | return c(data.err, data.text); 21 | default: throw new Error("Unknown message type: " + data.type); 22 | } 23 | }; 24 | 25 | var nextId = 0, pending = {}; 26 | function getFile(file, c) { 27 | postMessage({type: "getFile", name: file, id: ++nextId}); 28 | pending[nextId] = c; 29 | } 30 | 31 | function startServer(defs, plugins, scripts) { 32 | if (scripts) importScripts.apply(null, scripts); 33 | 34 | server = new tern.Server({ 35 | getFile: getFile, 36 | async: true, 37 | defs: defs, 38 | plugins: plugins 39 | }); 40 | } 41 | 42 | var console = { 43 | log: function(v) { postMessage({type: "debug", message: v}); } 44 | }; 45 | -------------------------------------------------------------------------------- /src/WebSite/Shared/CommonMarkdown.razor: -------------------------------------------------------------------------------- 1 | @inject IOptions SiteOption 2 | @inject NavigationManager Navigation 3 | 4 | @Title - @SiteOption.Value.AppTitle 5 | 6 |
7 |
8 |
9 |
10 |
11 |

@Title

12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 |
24 |
25 |
26 |
27 | 28 | @code 29 | { 30 | [Parameter] public string Title { get; set; } 31 | [Parameter] public string Markdown { get; set; } 32 | [Parameter] public string HtmlContent { get; set; } 33 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/lint/coffeescript-lint.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | // Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js 5 | 6 | // declare global: coffeelint 7 | 8 | (function(mod) { 9 | if (typeof exports == "object" && typeof module == "object") // CommonJS 10 | mod(require("../../lib/codemirror")); 11 | else if (typeof define == "function" && define.amd) // AMD 12 | define(["../../lib/codemirror"], mod); 13 | else // Plain browser env 14 | mod(CodeMirror); 15 | })(function(CodeMirror) { 16 | "use strict"; 17 | 18 | CodeMirror.registerHelper("lint", "coffeescript", function(text) { 19 | var found = []; 20 | var parseError = function(err) { 21 | var loc = err.lineNumber; 22 | found.push({from: CodeMirror.Pos(loc-1, 0), 23 | to: CodeMirror.Pos(loc, 0), 24 | severity: err.level, 25 | message: err.message}); 26 | }; 27 | try { 28 | var res = coffeelint.lint(text); 29 | for(var i = 0; i < res.length; i++) { 30 | parseError(res[i]); 31 | } 32 | } catch(e) { 33 | found.push({from: CodeMirror.Pos(e.location.first_line, 0), 34 | to: CodeMirror.Pos(e.location.last_line, e.location.last_column), 35 | severity: 'error', 36 | message: e.message}); 37 | } 38 | return found; 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/runmode/colorize.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror"), require("./runmode")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror", "./runmode"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/; 15 | 16 | function textContent(node, out) { 17 | if (node.nodeType == 3) return out.push(node.nodeValue); 18 | for (var ch = node.firstChild; ch; ch = ch.nextSibling) { 19 | textContent(ch, out); 20 | if (isBlock.test(node.nodeType)) out.push("\n"); 21 | } 22 | } 23 | 24 | CodeMirror.colorize = function(collection, defaultMode) { 25 | if (!collection) collection = document.body.getElementsByTagName("pre"); 26 | 27 | for (var i = 0; i < collection.length; ++i) { 28 | var node = collection[i]; 29 | var mode = node.getAttribute("data-lang") || defaultMode; 30 | if (!mode) continue; 31 | 32 | var text = []; 33 | textContent(node, text); 34 | node.innerHTML = ""; 35 | CodeMirror.runMode(text.join(""), mode, node); 36 | 37 | node.className += " cm-s-default"; 38 | } 39 | }; 40 | }); 41 | -------------------------------------------------------------------------------- /src/WebSite/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "http": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "dotnetRunMessages": true, 10 | "applicationUrl": "http://localhost:5001" 11 | }, 12 | "https": { 13 | "commandName": "Project", 14 | "launchBrowser": true, 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | }, 18 | "dotnetRunMessages": true, 19 | "applicationUrl": "https://localhost:5002;http://localhost:5003" 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | }, 28 | "Container (Dockerfile)": { 29 | "commandName": "Docker", 30 | "launchBrowser": true, 31 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", 32 | "environmentVariables": { 33 | "ASPNETCORE_HTTPS_PORTS": "8081", 34 | "ASPNETCORE_HTTP_PORTS": "8080" 35 | }, 36 | "publishAllPorts": true, 37 | "useSSL": true 38 | } 39 | }, 40 | "$schema": "http://json.schemastore.org/launchsettings.json", 41 | "iisSettings": { 42 | "windowsAuthentication": false, 43 | "anonymousAuthentication": true, 44 | "iisExpress": { 45 | "applicationUrl": "http://localhost:21738", 46 | "sslPort": 44385 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/AntBlazor/AntSearch.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | 3 | 13 | 14 | @code { 15 | [Parameter] public string Value { get; set; } 16 | [Parameter] public string Placeholder { get; set; } 17 | 18 | protected override async Task OnInitializedAsync() 19 | { 20 | await base.OnInitializedAsync(); 21 | InputAttributes.Clear(); 22 | InputAttributes.AddItem("value", Value); 23 | InputAttributes.AddItem("placeholder", Placeholder); 24 | } 25 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/scroll/simplescrollbars.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div { 2 | position: absolute; 3 | background: #ccc; 4 | -moz-box-sizing: border-box; 5 | box-sizing: border-box; 6 | border: 1px solid #bbb; 7 | border-radius: 2px; 8 | } 9 | 10 | .CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical { 11 | position: absolute; 12 | z-index: 6; 13 | background: #eee; 14 | } 15 | 16 | .CodeMirror-simplescroll-horizontal { 17 | bottom: 0; left: 0; 18 | height: 8px; 19 | } 20 | .CodeMirror-simplescroll-horizontal div { 21 | bottom: 0; 22 | height: 100%; 23 | } 24 | 25 | .CodeMirror-simplescroll-vertical { 26 | right: 0; top: 0; 27 | width: 8px; 28 | } 29 | .CodeMirror-simplescroll-vertical div { 30 | right: 0; 31 | width: 100%; 32 | } 33 | 34 | 35 | .CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler { 36 | display: none; 37 | } 38 | 39 | .CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div { 40 | position: absolute; 41 | background: #bcd; 42 | border-radius: 3px; 43 | } 44 | 45 | .CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical { 46 | position: absolute; 47 | z-index: 6; 48 | } 49 | 50 | .CodeMirror-overlayscroll-horizontal { 51 | bottom: 0; left: 0; 52 | height: 6px; 53 | } 54 | .CodeMirror-overlayscroll-horizontal div { 55 | bottom: 0; 56 | height: 100%; 57 | } 58 | 59 | .CodeMirror-overlayscroll-vertical { 60 | right: 0; top: 0; 61 | width: 6px; 62 | } 63 | .CodeMirror-overlayscroll-vertical div { 64 | right: 0; 65 | width: 100%; 66 | } 67 | -------------------------------------------------------------------------------- /src/CodeWF/Pages/Bbs/PostInfo.razor: -------------------------------------------------------------------------------- 1 | @page "/{year}/{month}/{slug}" 2 | @page "/post/{year}/{month}/{slug}" 3 | @page "/bbs/post/{year}/{month}/{slug}" 4 | 5 | @inherits BaseComponent 6 | @inject AppService AppService 7 | @inject IOptions SiteOption 8 | 9 | @model?.Title - @SiteOption.Value.AppTitle 10 | 11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
@model?.Title
20 | 21 | 24 | 25 |
26 |
27 |
28 |
29 |
30 | 31 |
32 | 33 |
34 |
35 | 36 | @code { 37 | private BlogPost? model; 38 | 39 | [Parameter] public string? Year { get; set; } 40 | [Parameter] public string? Month { get; set; } 41 | [Parameter] public string Slug { get; set; } 42 | 43 | protected override async Task OnInitAsync() 44 | { 45 | await base.OnInitAsync(); 46 | 47 | model = await AppService.GetPostBySlug(Slug); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/display/fullscreen.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.defineOption("fullScreen", false, function(cm, val, old) { 15 | if (old == CodeMirror.Init) old = false; 16 | if (!old == !val) return; 17 | if (val) setFullscreen(cm); 18 | else setNormal(cm); 19 | }); 20 | 21 | function setFullscreen(cm) { 22 | var wrap = cm.getWrapperElement(); 23 | cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, 24 | width: wrap.style.width, height: wrap.style.height}; 25 | wrap.style.width = ""; 26 | wrap.style.height = "auto"; 27 | wrap.className += " CodeMirror-fullscreen"; 28 | document.documentElement.style.overflow = "hidden"; 29 | cm.refresh(); 30 | } 31 | 32 | function setNormal(cm) { 33 | var wrap = cm.getWrapperElement(); 34 | wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, ""); 35 | document.documentElement.style.overflow = ""; 36 | var info = cm.state.fullScreenRestore; 37 | wrap.style.width = info.width; wrap.style.height = info.height; 38 | window.scrollTo(info.scrollLeft, info.scrollTop); 39 | cm.refresh(); 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/scroll/scrollpastend.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) { 15 | if (old && old != CodeMirror.Init) { 16 | cm.off("change", onChange); 17 | cm.off("refresh", updateBottomMargin); 18 | cm.display.lineSpace.parentNode.style.paddingBottom = ""; 19 | cm.state.scrollPastEndPadding = null; 20 | } 21 | if (val) { 22 | cm.on("change", onChange); 23 | cm.on("refresh", updateBottomMargin); 24 | updateBottomMargin(cm); 25 | } 26 | }); 27 | 28 | function onChange(cm, change) { 29 | if (CodeMirror.changeEnd(change).line == cm.lastLine()) 30 | updateBottomMargin(cm); 31 | } 32 | 33 | function updateBottomMargin(cm) { 34 | var padding = ""; 35 | if (cm.lineCount() > 1) { 36 | var totalH = cm.display.scroller.clientHeight - 30, 37 | lastLineH = cm.getLineHandle(cm.lastLine()).height; 38 | padding = (totalH - lastLineH) + "px"; 39 | } 40 | if (cm.state.scrollPastEndPadding != padding) { 41 | cm.state.scrollPastEndPadding = padding; 42 | cm.display.lineSpace.parentNode.style.paddingBottom = padding; 43 | cm.setSize(); 44 | } 45 | } 46 | }); 47 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/plugins/test-plugin/test-plugin.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Test plugin for Editor.md 3 | * 4 | * @file test-plugin.js 5 | * @author pandao 6 | * @version 1.2.0 7 | * @updateTime 2015-03-07 8 | * {@link https://github.com/pandao/editor.md} 9 | * @license MIT 10 | */ 11 | 12 | (function() { 13 | 14 | var factory = function (exports) { 15 | 16 | var $ = jQuery; // if using module loader(Require.js/Sea.js). 17 | 18 | exports.testPlugin = function(){ 19 | alert("testPlugin"); 20 | }; 21 | 22 | exports.fn.testPluginMethodA = function() { 23 | /* 24 | var _this = this; // this == the current instance object of Editor.md 25 | var lang = _this.lang; 26 | var settings = _this.settings; 27 | var editor = this.editor; 28 | var cursor = cm.getCursor(); 29 | var selection = cm.getSelection(); 30 | var classPrefix = this.classPrefix; 31 | 32 | cm.focus(); 33 | */ 34 | //.... 35 | 36 | alert("testPluginMethodA"); 37 | }; 38 | 39 | }; 40 | 41 | // CommonJS/Node.js 42 | if (typeof require === "function" && typeof exports === "object" && typeof module === "object") 43 | { 44 | module.exports = factory; 45 | } 46 | else if (typeof define === "function") // AMD/CMD/Sea.js 47 | { 48 | if (define.amd) { // for Require.js 49 | 50 | define(["editormd"], function(editormd) { 51 | factory(editormd); 52 | }); 53 | 54 | } else { // for Sea.js 55 | define(function(require) { 56 | var editormd = require("./../../editormd"); 57 | factory(editormd); 58 | }); 59 | } 60 | } 61 | else 62 | { 63 | factory(window.editormd); 64 | } 65 | 66 | })(); 67 | -------------------------------------------------------------------------------- /src/CodeWF/Shared/PostFooter.razor: -------------------------------------------------------------------------------- 1 | @inject IOptions SiteOption 2 | 3 | 38 | 39 | @code 40 | { 41 | [Parameter] public BlogPost? Model { get; set; } 42 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/UDocMenu.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 5 | @if (_contents is { Count: > 0 }) 6 | { 7 |
    8 | @foreach (var content in _contents) 9 | { 10 |
  • 11 | @if (content.Children?.Count > 0) 12 | { 13 |
    @content.Name
    14 |
      15 | @foreach (var child in content.Children) 16 | { 17 |
    • 18 | @child.Name 19 |
    • 20 | } 21 |
    22 | } 23 | else 24 | { 25 | @content.Name 26 | } 27 |
  • 28 | } 29 |
30 | } 31 |
32 | 33 | @code { 34 | private List? _contents { get; set; } 35 | 36 | protected override async Task OnInitAsync() 37 | { 38 | await base.OnInitAsync(); 39 | 40 | _contents = await AppService.GetAllDocItemsAsync(); 41 | } 42 | 43 | private string GetUrl(DocItem item) => $"/doc/{item.Slug}"; 44 | 45 | private bool IsActive(string slug) 46 | { 47 | var uri = Navigation.Uri; 48 | if (string.Equals(slug, _contents?.FirstOrDefault()?.Slug, StringComparison.CurrentCultureIgnoreCase)) 49 | { 50 | return true; 51 | } 52 | 53 | return uri.EndsWith($"/{slug}"); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /src/CodeWF/Shared/UToolMenu.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseComponent 2 | @inject AppService AppService 3 | 4 | 5 | @if (_contents is { Count: > 0 }) 6 | { 7 |
    8 | @foreach (var content in _contents) 9 | { 10 |
  • 11 | @if (content.Children?.Count > 0) 12 | { 13 |
    @content.Name
    14 |
      15 | @foreach (var child in content.Children) 16 | { 17 |
    • 18 | @child.Name 19 |
    • 20 | } 21 |
    22 | } 23 | else 24 | { 25 | @content.Name 26 | } 27 |
  • 28 | } 29 |
30 | } 31 |
32 | 33 | @code { 34 | private List? _contents { get; set; } 35 | 36 | protected override async Task OnInitAsync() 37 | { 38 | await base.OnInitAsync(); 39 | 40 | _contents = await AppService.GetAllToolItemsAsync(); 41 | } 42 | 43 | private string GetUrl(ToolItem item) => $"/tool/{item.Slug}"; 44 | 45 | private bool IsActive(string slug) 46 | { 47 | var uri = Navigation.Uri; 48 | if (string.Equals(slug, _contents?.FirstOrDefault()?.Slug, StringComparison.CurrentCultureIgnoreCase)) 49 | { 50 | return true; 51 | } 52 | 53 | return uri.EndsWith($"/{slug}"); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/fold/indent-fold.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.registerHelper("fold", "indent", function(cm, start) { 15 | var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line); 16 | if (!/\S/.test(firstLine)) return; 17 | var getIndent = function(line) { 18 | return CodeMirror.countColumn(line, null, tabSize); 19 | }; 20 | var myIndent = getIndent(firstLine); 21 | var lastLineInFold = null; 22 | // Go through lines until we find a line that definitely doesn't belong in 23 | // the block we're folding, or to the end. 24 | for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) { 25 | var curLine = cm.getLine(i); 26 | var curIndent = getIndent(curLine); 27 | if (curIndent > myIndent) { 28 | // Lines with a greater indent are considered part of the block. 29 | lastLineInFold = i; 30 | } else if (!/\S/.test(curLine)) { 31 | // Empty lines might be breaks within the block we're trying to fold. 32 | } else { 33 | // A non-empty line at an indent equal to or less than ours marks the 34 | // start of another block. 35 | break; 36 | } 37 | } 38 | if (lastLineInFold) return { 39 | from: CodeMirror.Pos(start.line, firstLine.length), 40 | to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length) 41 | }; 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/fold/markdown-fold.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.registerHelper("fold", "markdown", function(cm, start) { 15 | var maxDepth = 100; 16 | 17 | function isHeader(lineNo) { 18 | var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0)); 19 | return tokentype && /\bheader\b/.test(tokentype); 20 | } 21 | 22 | function headerLevel(lineNo, line, nextLine) { 23 | var match = line && line.match(/^#+/); 24 | if (match && isHeader(lineNo)) return match[0].length; 25 | match = nextLine && nextLine.match(/^[=\-]+\s*$/); 26 | if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2; 27 | return maxDepth; 28 | } 29 | 30 | var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1); 31 | var level = headerLevel(start.line, firstLine, nextLine); 32 | if (level === maxDepth) return undefined; 33 | 34 | var lastLineNo = cm.lastLine(); 35 | var end = start.line, nextNextLine = cm.getLine(end + 2); 36 | while (end < lastLineNo) { 37 | if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break; 38 | ++end; 39 | nextLine = nextNextLine; 40 | nextNextLine = cm.getLine(end + 2); 41 | } 42 | 43 | return { 44 | from: CodeMirror.Pos(start.line, firstLine.length), 45 | to: CodeMirror.Pos(end, cm.getLine(end).length) 46 | }; 47 | }); 48 | 49 | }); 50 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/hint/anyword-hint.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | var WORD = /[\w$]+/, RANGE = 500; 15 | 16 | CodeMirror.registerHelper("hint", "anyword", function(editor, options) { 17 | var word = options && options.word || WORD; 18 | var range = options && options.range || RANGE; 19 | var cur = editor.getCursor(), curLine = editor.getLine(cur.line); 20 | var end = cur.ch, start = end; 21 | while (start && word.test(curLine.charAt(start - 1))) --start; 22 | var curWord = start != end && curLine.slice(start, end); 23 | 24 | var list = [], seen = {}; 25 | var re = new RegExp(word.source, "g"); 26 | for (var dir = -1; dir <= 1; dir += 2) { 27 | var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir; 28 | for (; line != endLine; line += dir) { 29 | var text = editor.getLine(line), m; 30 | while (m = re.exec(text)) { 31 | if (line == cur.line && m[0] === curWord) continue; 32 | if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) { 33 | seen[m[0]] = true; 34 | list.push(m[0]); 35 | } 36 | } 37 | } 38 | } 39 | return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)}; 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/css/toc.css: -------------------------------------------------------------------------------- 1 | /*toc*/ 2 | @media (max-width: 800px) { 3 | #toc { 4 | display: none; 5 | max-width: 0px; 6 | } 7 | } 8 | @media (min-width: 768px) { 9 | #toc { 10 | display: unset; 11 | left: calc((100vw + 0720px) / 2 - 280px); 12 | max-width: calc((100vw - 0720px) / 2 + 220px); 13 | } 14 | } 15 | @media (min-width: 992px) { 16 | #toc { 17 | left: calc((100vw + 0960px) / 2 - 280px); 18 | max-width: calc((100vw - 0960px) / 2 + 220px); 19 | } 20 | } 21 | @media (min-width: 1200px) { 22 | #toc { 23 | left: calc((100vw + 1140px) / 2 - 280px); 24 | max-width: calc((100vw - 1140px) / 2 + 220px); 25 | } 26 | } 27 | @media (min-width: 1920px) { 28 | #toc { 29 | left: calc((100vw + 1360px) / 2 - 280px); 30 | max-width: calc((100vw - 1360px) / 2 + 220px); 31 | } 32 | } 33 | 34 | #toc { 35 | padding: 1em; 36 | position: fixed; 37 | top: 100vh; 38 | left: auto; 39 | right: 2%; 40 | width: auto; 41 | height: auto; 42 | min-width: 150px; 43 | max-height: 70vh; 44 | overflow-y: auto; 45 | background-color: #fff; /* 可以设置背景颜色 */ 46 | box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1); /* 可选的阴影效果 */ 47 | z-index: 1000; /* 确保在其他元素之上 */ 48 | transition: all 0.5s ease; 49 | &.toc-show { 50 | top: 100px; 51 | } 52 | a { 53 | display: block; /* 使链接成为块级元素 */ 54 | white-space: nowrap; /* 不允许换行 */ 55 | overflow: hidden; /* 隐藏溢出内容 */ 56 | text-overflow: ellipsis; /* 使用省略号替代溢出部分 */ 57 | padding-block: 5px; 58 | } 59 | 60 | .item-title { 61 | border-bottom: 1px solid black; 62 | padding-bottom: 4px; 63 | margin-bottom: 10px; 64 | } 65 | 66 | .item-h2 { 67 | padding-inline-start: 8px; 68 | } 69 | 70 | .item-h3 { 71 | padding-inline-start: 16px; 72 | } 73 | 74 | .item-h4 { 75 | padding-inline-start: 24px; 76 | } 77 | } 78 | 79 | /*toc*/ 80 | -------------------------------------------------------------------------------- /src/CodeWF/Pages/Bbs/Album.razor: -------------------------------------------------------------------------------- 1 | @page "/bbs/album" 2 | @page "/bbs/album/{Slug}" 3 | 4 | @inherits ListComponent 5 | @inject IOptions SiteOptions 6 | @inject AppService AppService 7 | 8 | 博文 - @SiteOptions.Value.AppTitle 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | @if (!(_blogPosts?.Total > 0)) 19 | { 20 | 21 | } 22 | else 23 | { 24 | foreach (var post in _blogPosts.Data) 25 | { 26 | 27 | } 28 | 29 |
30 | 31 |
32 | } 33 |
34 |
35 |
36 | 37 |
38 | 39 |
40 |
41 | 42 | @code { 43 | private PageData? _blogPosts; 44 | 45 | [Parameter] public string? Slug { get; set; } 46 | [SupplyParameterFromQuery] public string? Key { get; set; } 47 | 48 | protected override async Task OnInitAsync() 49 | { 50 | await base.OnInitAsync(); 51 | if (string.IsNullOrWhiteSpace(Slug)) 52 | { 53 | Slug = ConstantUtil.DefaultCategory; 54 | } 55 | 56 | if (string.IsNullOrWhiteSpace(Key)) 57 | { 58 | Key = Context.Request.Get("Key"); 59 | } 60 | 61 | _blogPosts = await AppService.GetPostByAlbum(Page, ConstData.PageSize, Slug, Key); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /src/CodeWF/wwwroot/lib/codemirror/addon/edit/continuelist.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/, 15 | emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/, 16 | unorderedListRE = /[*+-]\s/; 17 | 18 | CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { 19 | if (cm.getOption("disableInput")) return CodeMirror.Pass; 20 | var ranges = cm.listSelections(), replacements = []; 21 | for (var i = 0; i < ranges.length; i++) { 22 | var pos = ranges[i].head, match; 23 | var eolState = cm.getStateAfter(pos.line); 24 | var inList = eolState.list !== false; 25 | var inQuote = eolState.quote !== false; 26 | 27 | if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) { 28 | cm.execCommand("newlineAndIndent"); 29 | return; 30 | } 31 | if (cm.getLine(pos.line).match(emptyListRE)) { 32 | cm.replaceRange("", { 33 | line: pos.line, ch: 0 34 | }, { 35 | line: pos.line, ch: pos.ch + 1 36 | }); 37 | replacements[i] = "\n"; 38 | 39 | } else { 40 | var indent = match[1], after = match[4]; 41 | var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0 42 | ? match[2] 43 | : (parseInt(match[3], 10) + 1) + "."; 44 | 45 | replacements[i] = "\n" + indent + bullet + after; 46 | } 47 | } 48 | 49 | cm.replaceSelections(replacements); 50 | }; 51 | }); 52 | -------------------------------------------------------------------------------- /src/CodeWF/Pages/Bbs/Category.razor: -------------------------------------------------------------------------------- 1 | @page "/bbs" 2 | @page "/bbs/cat" 3 | @page "/bbs/cat/{Slug}" 4 | 5 | @inherits ListComponent 6 | @inject IOptions SiteOptions 7 | @inject AppService AppService 8 | 9 | 博文分类 - @SiteOptions.Value.AppTitle 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | @if (!(_blogPosts?.Total > 0)) 20 | { 21 | 22 | } 23 | else 24 | { 25 | foreach (var post in _blogPosts.Data) 26 | { 27 | 28 | } 29 | 30 |
31 | 32 |
33 | } 34 |
35 |
36 |
37 | 38 |
39 | 40 |
41 |
42 | 43 | @code { 44 | private PageData? _blogPosts; 45 | 46 | [Parameter] public string? Slug { get; set; } 47 | [SupplyParameterFromQuery] public string? Key { get; set; } 48 | 49 | protected override async Task OnInitAsync() 50 | { 51 | await base.OnInitAsync(); 52 | if (string.IsNullOrWhiteSpace(Slug)) 53 | { 54 | Slug = ConstantUtil.DefaultCategory; 55 | } 56 | 57 | if (string.IsNullOrWhiteSpace(Key)) 58 | { 59 | Key = Context.Request.Get("Key"); 60 | } 61 | 62 | _blogPosts = await AppService.GetPostByCategory(Page, ConstData.PageSize, Slug, Key); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/WebSite/wwwroot/js/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v1.0.0 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | !function(e){"use strict";window.Toc={helpers:{findOrFilter:function(e,t){var n=e.find(t);return e.filter(t).add(n).filter(":not([data-toc-skip])")},generateUniqueIdBase:function(t){var n=e(t).text(),r=n.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g,"-");return r||t.tagName.toLowerCase()},generateUniqueId:function(e){for(var t=this.generateUniqueIdBase(e),n=0;;n++){var r=t;if(n>0&&(r+="-"+n),!document.getElementById(r))return r}},generateAnchor:function(e){if(e.id)return e.id;var t=this.generateUniqueId(e);return e.id=t,t},createNavList:function(){return e('')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(t,n){var r=e('');r.attr("href","#"+t),r.text(n);var a=e("
  • ");return a.append(r),a},generateNavItem:function(t){var n=this.generateAnchor(t),r=e(t),a=r.data("toc-text")||r.text();return this.generateNavEl(n,a)},getTopLevel:function(e){for(var t=1;t<=6;t++){var n=this.findOrFilter(e,"h"+t);if(n.length>1)return t}return 1},getHeadings:function(e,t){var n="h"+t,r=t+1,a="h"+r;return this.findOrFilter(e,n+","+a)},getNavLevel:function(e){return parseInt(e.tagName.charAt(1),10)},populateNav:function(e,t,n){var r,a=e,i=this;n.each(function(n,o){var s=i.generateNavItem(o),u=i.getNavLevel(o);u===t?a=e:r&&a===e&&(a=i.createChildNavList(r)),a.append(s),r=s})},parseOps:function(t){var n;return n=t.jquery?{$nav:t}:t,n.$scope=n.$scope||e(document.body),n}},init:function(e){e=this.helpers.parseOps(e),e.$nav.attr("data-toggle","toc");var t=this.helpers.createChildNavList(e.$nav),n=this.helpers.getTopLevel(e.$scope),r=this.helpers.getHeadings(e.$scope,n);this.helpers.populateNav(t,n,r)}},e(function(){e('nav[data-toggle="toc"]').each(function(t,n){var r=e(n);Toc.init(r)})})}(jQuery); -------------------------------------------------------------------------------- /src/CodeWF/Pages/Tool/Web/SlugifyString.razor: -------------------------------------------------------------------------------- 1 | @inject IOptions SiteOptions 2 | 3 | 标题转URL别名 - @SiteOptions.Value.AppTitle 4 | 5 |

    标题转URL别名

    6 |

    将标题转换为URL友好的格式

    7 | 8 |

    需要转换的标题

    9 |