• 上手 Gatsby 入门教程
    Gatsby 项目结构建议使用 Starter 修改着理解 Gatsby,我用的是 Gatsby + Netlify CMS Starter。完整的 Gatsby 项目结构可以看文档,这里针对搭建博客用到的功能说明一下。    /src/pages 目录下的组件会被生成同名页面。    /src/templates 目录下放渲染数据的模板组件,如渲染 Markdown 文章,在其它博客系统中一般叫 layout。    /src/components 一般放其它共用的组件。    /static 放其它静态资源,会跳过 Webpack 直接复制过去。接下来是两个比较常用的配置文件,需要修改时参考 Starter 改即可。    /gatsby-config.js 基本用来配置两个东西:    siteMetadata 放一些全局信息,这些信息在每个页面都可以通过 GraphQL 获取到。    plugins 配置插件,这个按用到时按该插件文档说明弄即可。    /gatsby-node.js 可以调用 Gatsby node APIs干一些自动化的东西。一般有两个常用场景:        添加额外的配置,比如为 Markdown 文章生成自定义路径。        生成 /src/pages 以外的页面文件,如为每个 Markdown 文章生成页面文件。    此外还有两个不那么常用的配置文件。        /gatsby-browser.js 可以调用 Gatsby 浏览器 APIs,一般插件才会用到,如滚动到特定位置。        /gatsby-ssr.js 服务器渲染的配置,一般也是插件才用到。    这就是搭建 Gatsby 博客的基本结构了,可以看到非常简单,且因为其丰富的生态,其它底层接口基本不需要用到。但接下来还是会有一些小坑,第一个便是 GraphQL,我们将马上来分析。为什么用 GraphQL    在上一节介绍了选择 Gatsby 的原因,其中提到了 Gatsby 使用 GraphQL 。大家可能会有疑惑,不是建静态博客么,怎么会有 GraphQL?难道还要部署服务器?    其实这里 GraphQL 并不是作为服务器端部署,而是作为 Gatsby 在本地管理资源的一种方式。    通过 GraphQL 统一管理实际上非常方便,因为作为一个数据库查询语言,它有非常完备的查询语句,与 JSON 相似的描述结构,再结合 Relay 的 Connections 方式处理集合,管理资源不再需要自行引入其它项目,大大减轻了维护难度。带魔法的 GraphQL    这里也是 Gatsby 的第一个坑。在 Gatsby 中,根据 js 文件的位置不同,使用 GraphQL 有两种形式,且 Gatsby 对其做了魔法,在 src /pages 下的页面可以直接 export GraphQL 查询,在其它页面需要用 StaticQuery 组件或者 useStaticQuery hook。    这里面查询语句虽然写的是字符串,但其实这些查询语句不会出现在最终的代码中,Gatsby 会先对其抽取。    个人其实不太喜欢魔法,因为会增加初学者的理解难度。但不得不承认魔法确实很方便,就是用了魔法的项目应该在文档最显眼的地方说明一遍。快速上手 GraphQL    GraphQL 结构跟最终数据很相似,基本语法也非常简单,看看官方文档即可。一个快速上手的方式是访问项目开发时(默认 http://localhost:8000)的 /___graphql 页面,通过 GraphiQL 编辑器右侧可以浏览所有能够查询的资源。    另一个需要理解的是 Relay 的 Connections 概念,你会发现 Gatsby 里所有的数据集合都是以这种方式查询。推荐阅读 Apollo 团队分享的文章。    对 Connections 细致的理解往往是实现分页等底层需求时才需要,而这些均有插件完成。一般使用时只需要知道集合里每个项目的数据在 edges.node 中,同时通过 GraphiQL 浏览其它可以使用的数据。如对于 Markdown 文章,相应插件提供了字数统计以及阅读时长等数据,均可通过 GraphQL 直接获取。Debug GraphQL    Gatsby 魔法带来的另外一个坑是 GraphQL 报错信息不全,可能会默默被吞掉,也可能无法定位到最终文件。    我在修改 starter 时踩到一个坑是复制组件时忘了修改 static query 查询语句的名称,导致重名报错。    避免错误最好方式是在 GraphiQL 编辑器中写好运行无误再复制到组件中。Remark 插件坑    Gatsby 中处理 markdown 最常用也是默认的插件是 gatsby-transformer-remark。这个插件对 markdown 文件解析后会生成 MarkdownRemark GraphQL 节点,其中 front matters 数据也会被解析出来。同时 MarkdownRemark 的集合对应为 allMarkdownRemark connections。    对于 connections 节点我们一般可以用 sort 和 filter 来筛选处理数据(可在 GraphiQL 编辑器中浏览),这里有一个坑便是如果要处理 front matters 数据,它们必须存在所有查询的 markdown 文件上并且具有相同的类型,插件才会生成相应的 fields,否则可能会抛出异常或者更糟糕的,默默失败了。    避免方式同上,先在 GraphiQL 编辑器中运行一遍,看看筛选的结果是否正确。    另外一种处理方式是在 /gatsby-node.js 中通过 onCreateNode 钩子,在生成 markdown 相关节点时手工处理,确保节点存在。    这在实现草稿和上下篇的时候会用到,具体例子我会在后续章节中提到。为什么选择 Netlify CMS    搭建 Gatsby 博客其实不需要 CMS 都是可以的,编写 Markdown 然后 build 即可。但这么做还是略嫌不便,通过 CMS 一般可以在一个可视化的在线环境中编辑文章,然后一键即可发布。    Gatsby 主流的两个 CMS 是 Contentful 和 Netlify CMS。    对于 Contentful 来说,文章是放在 Contentful 的服务器上的,管理也是通过 Contentful 提供的工具。当然其质量还是不错的,喜欢的可以参照官方的教程搭建。    Netlify CMS 是跟项目一起发布的,默认是在 /admin 页面下。文章也是存在源项目中,就是原来默认的 Markdown 文件。Netlify CMS 借助 Oauth 把写好的 Markdown 文件推送到项目源码的仓库上,再配合 Netlify 检测仓库变动自动构建发布。当然后者也不是必须的,可以换其它方式自动构建。    Netlify CMS 的优点是开源免费,文章跟项目源码在一起,界面可以高度自定义,甚至可以自行扩充 React 组件,基本满足简单的博客编写需求。配置 Netlify CMS    如果用官方的 starter配置将会非常简单。此 starter 默认使用 Github 作为仓库,Netlify 作为自动构建服务器。配置 Widgets    默认的 /static/admin/config.yml 已经配置好了大部分,如果对文章 Markdown 添加了自定义的 front matters 则需要再做些细调。    Widgets 代表了在 CMS 中可输入的模块,官方为常见的类型都提供了默认的 widgets ,没有满足的也可以自定义。    如我的博客中每篇文章都有一个 quote 域放些引用文字,那么在配置中添加上 fields: - label: "Quote" name: "quote" widget: "object" fields: - {label: "Content", name: "content", widget: "text", default: "", required: false} - {label: "Author", name: "author", widget: "string", default: "", required: false} - {label: "Source", name: "source", widget: "string", default: "", required: false}    如此即可在 CMS 中填写相关信息。配置预览    CMS 中提供了文章预览界面,如果需要自定义只需修改 /src/cms/ 下相应的文件即可,就是简单的 React 组件。    以上便是 Netlify CMS 最常用的配置,只需简单的修改博客现在就能跑起来了。接下来我们会通过实现草稿模式和上下篇文章来深入理解 Gatsby 的机制。    迁移博客需要考虑的一个重要问题便是路径兼容。我们当然不希望迁移后原有的链接无法访问,这不仅影响到 SEO ,更带来了不好的用户访问体验。本文将聊聊怎么让 Gatsby 兼容 Jekyll 式路径。Gatsby 如何生成特定页面    一般来说,在 /src/pages/ 目录下的组件会自动生成相应路径的页面,但如果是其它类型的文件就不会了。我们可以通过 Gatsby 的 Node APIs 来生成特定页面。    在 /gatsby-node.js 中配置 Gatsby Node APIs,如果项目是基于 starter 的话你很可能会发现里面已经有相应的配置。    我们通过声明 exports.createPages 钩子来配置页面生成,在回调中通过调用 actions.createPage 来生成某个指定页面。这个方法接受一个配置参数,其中的 path 域代表了生成页面的路径。 exports.createPages = ({ actions, graphql }) => { actions.createPage({ path, // ... }) }指定博客页面    那么我们怎么知道该生成哪些页面呢?这里通过 exports.createPages 回调中的 graphql 来查询 Markdown 文件。 exports.createPages = ({ actions, graphql }) => { const { createPage } = actions return graphql(` { allMarkdownRemark(sort: { order: ASC, fields: [frontmatter___date] }) { edges { node { id fields { slug } frontmatter { path title layout } } } } } `).then(result => { if (result.errors) { result.errors.forEach(e => console.error(e.toString())) return Promise.reject(result.errors) } // ... }) }    Netlify CMS 会在 Markdown front matters 中的 path 域生成路径。根据默认的 /static/admin/config.yml 我们的路径应该是 /blog/{{year}}-{{month}}-{{day}}-{{slug}}/ ,这个可能跟旧博客不一样,如 Jekyll 是 /{{year}}/{{month}}/{{day}}/{{slug}}/ 。修改 Markdown 节点    在 Remark 插件生成的 Markdown 节点中,我们可以往 fields 域放一些自定义的变量。这里我们把自定义的路径存到 fields.slug 中。    通过 /gatsby-node.js 中的 exports.onCreateNode 钩子我们可以在生成节点的时候进行拦截处理。你可能发现文件里面已经有一些配置的代码了,我们这里只关注 Markdown 相关的。 exports.onCreateNode = ({ node, actions, getNode }) => { const { createNodeField } = actions if (node.internal.type === `MarkdownRemark`) { // Jeykll style post path const filepath = createFilePath({ node, getNode }) createNodeField({ node, name: 'slug', value: filepath.replace( /^\/blog\/([\d]{4})-([\d]{2})-([\d]{2})-/, '/$1/$2/$3/' ) }) } }    我们把原有的路径值换成了自定义值并存在了 fileds.slug 中。创建页面    回到我们前面的查询,得到需要的数据之后只需要对每个页面调用 actions.createPage 即可。  exports.createPages = ({ actions, graphql }) => { const { createPage } = actions return graphql(` { allMarkdownRemark(sort: { order: ASC, fields: [frontmatter___date] }) { edges { node { id fields { slug } frontmatter { path title layout } } } } } `).then(result => { if (result.errors) { result.errors.forEach(e => console.error(e.toString())) return Promise.reject(result.errors) } const { edges } = result.data.allMarkdownRemark const options = edges.map(edge => ({ path: edge.node.fields.slug, title: edge.node.frontmatter.title, component: path.resolve( `src/templates/${edge.node.frontmatter.layout}.js` ), // additional data can be passed via context context: { id: edge.node.id } })) options.forEach(option => createPage(option)) }) }     也许你会问为什么不在这里直接计算自定义路径而是要存到 fields.slug 中。这是因为这个路径我们可能还会在其它地方用到,存起来就不必多处计算了。    上面代码中可以注意到还有个 context 域,这个域中的数据会被传到 component 的 props 中。这样我们在模板组件中通过 pageContext.id 便可判断当前渲染的文件。    通过实现自定义路径基本上可以了解 Gatsby 页面生成的方式了。下节中我会继续谈谈其它个性化的配置,如草稿模式和显示上下篇博文。草稿模式    草稿模式即可以将文章保存为草稿而不被渲染出来。方式是在 front matters 中设置一个 draft 布尔域,以此域作为渲染参考。    坑    这里有一个地方需要注意,前面文章提过,Markdown 插件需要所有文章中都有 draft 域且都是布尔类型才会生成相应的 GraphQL 查询。如果是新的博客这个问题不大,如果是迁移过来的,有两个解决方式,第一个是手动写个脚本给文章都补上域,另一个是利用 Gatsby 的 Node APIs 在 fields 上生成特定域,鲁棒性更好些。自动生成域    观察 Remark 插件生成的 GraphQL 类型,我们可以发现,front matters 都被放在 frontmatter 域中,而与之同级的有一个前面文章提到过的 fields 域,用来放自定义生成的数据。    Gatsby 在生成 GraphQL 节点时提供了钩子 onCreateNode,我们利用这个钩子往 fields 中放自定义的数据。    编辑 /gatsby-node.js ,如果是用了 starter 的话这里很可能已经有其它的代码,已有的不需要动,添加我们需要的即可。 exports.onCreateNode = ({ node, actions, getNode }) => { const { createNodeField } = actions if (node.internal.type === `MarkdownRemark`) { createNodeField({ node, name: 'draft', value: Boolean(node.frontmatter.draft) }) } }    如此 fields 中就保证了会有 draft 这个域了。过滤草稿    有了标记之后,在生成页面的地方我们就需要过滤草稿。    首先是普通的文章页面生成,这个是在 createPages 钩子中,如果你的博客只有文章用到 Markdown 的话,可以在 GraphQL 查询中直接过滤,否则我们用前面文章的方法,先取所有 Markdown 文件再根据渲染的模板来分别处理各种类型的文章。    注意我把模板域的名字换成了自己更习惯的 layout,原来的 starter 中应该叫 templateKey。修改其实也很简单,搜索所有文件替换关键字即可。 options .filter( (_, i) => !( edges[i].node.frontmatter.layout === 'blog-post' && edges[i].node.fields.draft ) ) .forEach(option => createPage(option))    我在主页中也列举了最近的几篇文章,这里也需要过滤草稿,可以直接在 GraphQL 中过滤。 query IndexQuery { latestPosts: allMarkdownRemark( sort: { order: DESC, fields: [frontmatter___date] } filter: { fields: { draft: { ne: true } } frontmatter: { layout: { eq: "blog-post" } } } limit: 5 ) { edges { node { excerpt(pruneLength: 200) id fields { slug } frontmatter { title description layout date(formatString: "MMMM DD, YYYY") } } } } }    其它地方同理。上下篇    在文章页面中我们通常会加入上下篇来引导继续浏览。这里我们同样在 createPages 钩子中处理,但这回我们添加到 context 域中,这个域里的数据会作为 props 传到模板组件中。    在 createPage 生成文章页面前添加处理代码计算上下篇: options .filter( (_, i) => edges[i].node.frontmatter.layout === 'blog-post' && !edges[i].node.fields.draft ) .forEach((option, i, blogPostOptions) => { option.context.prev = i === 0 ? null : { title: blogPostOptions[i - 1].title, path: blogPostOptions[i - 1].path } option.context.next = i === blogPostOptions.length - 1 ? null : { title: blogPostOptions[i + 1].title, path: blogPostOptions[i + 1].path } })    然后在文章的 /src/templates/blog-post.js 组件里,接收 pageContext props,就可以使用上面传入的数据了。这是我的例子。    通过实现这几个功能我们了解了 Gatsby 页面生成的方式以及其 Node APIs 的基本使用。Gatsby 的功能远不止这些,官方文档写得非常详细,需要实现其它功能建议先去看看有无现有的例子。本系列到这里暂告一段落,谢谢你的阅读,希望能对你搭建 Gatsby 博客有所帮助。
  • 4135415431
    5315143 484460
  • 测试联盟编辑器
    **markdown发帖** *markdown发帖* markdown发帖 ~~markdown发帖~~ # markdown发帖markdown发帖> markdown发帖 ```js print(markdown发帖) ``` 1. markdown发帖 2. 3123123 3. 12312 4. 312 5. 3123123123 - markdown发帖 - 3123 - 123 - 123 - 213 - 213 - 12 - 3123 [link](https://www.github.com) [link](https://www.githubliqian.com) [link](https://www.githubjavascript.com) 标题 1 | 标题 2 | 标题 3 ----- | ----- | ----- 文本 1 | 文本 2 | 文本 3 文本 1 | 文本 2 | 文本 3 ---- markdown发帖 ![t2e22st21.gif](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/10/002747wv25qfebiu5frokc.gif) ![v2-8021c989656b8b6d770cf9158f639c91_1440w.jpeg](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/10/002812x4fxcwrydoo4naul.jpeg) ![t44es433t3.gif](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/10/002821gpes8jcbwu82armp.gif) ![te2s22t2.gif](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/10/002833dvvhc1ltj1o2ovcj.gif) >
  • [整体安全] 【漏洞预警】Gitlab markdown 远程代码执行漏洞
    漏洞描述:Gitlab是一款基于Git 的完全集成的软件开发平台,且具有wiki以及在线编辑、issue跟踪功能、CI/CD 等功能。2021年3月18日Gitlab官方发布安全更新,修复了一处远程代码执行漏洞,攻击者可构造恶意请求,在Gitlab服务器上执行任意代码,控制服务器。提醒Gitlab用户尽快采取安全措施阻止漏洞攻击。漏洞评级:Gitlab markdown 远程代码执行漏洞 严重。影响版本:Gitlab CE/EE < 13.9.4Gitlab CE/EE < 13.8.6Gitlab CE/EE < 13.7.9安全版本:Gitlab CE/EE 13.9.4Gitlab CE/EE 13.8.6Gitlab CE/EE 13.7.9安全建议:1. 升级Gitlab至安全版本。2. 将Gitlab服务器部署于内网,或通过设置安全组仅对可信地址开放。相关链接:https://about.gitlab.com/releases/2021/03/16/security-release-gitlab-13-9-4-released/#remote-code-execution-via-unsafe-user-controlled-markdown-rendering-options
  • 测试markdown
    **加粗加粗加粗加粗加粗加粗加粗** *倾斜倾斜倾斜倾斜倾斜倾斜倾斜倾斜* 下划线下划线下划线下划线下划线下划线 ~~删除线删除线删除线删除线删除线删除线~~ # 标题标题标题标题标题标题居中居中居中居中居中居中> 引用引用引用引用引用引用引用引用 1. 有序序号 2. 有序序号 3. 有序序号 - 无序序号 - 无序序号 - 无序序号 [超链接白名单可以跳转](https://bbs.huaweicloud.com/forum/thread-97190-1-1.html) [超链接不是白名单不能跳转](https://bbs.liqian12312312312.com) 标题 1 | 标题 2 | 标题 3 ----- | ----- | ----- 文本 1 | 文本 2 | 文本 3 文本 1 | 文本 2 | 文本 3 ---- ![版主推荐.jpg](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202102/04/151754o5shehso6ihibpal.jpg) ![160854xzufo7jwpmzc01yx.jpg](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202102/04/1518016ifhwkpg0hxxk6ix.jpg) ![120080.jpg](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202102/04/151807p2drs6hdezj7idyx.jpg) ####
  • [内容拦截申诉] 【博客】【建站分享:Gitee+PicGo 搭建Markdown图床】审核未通过
    【功能模块】【操作步骤&问题现象】发表博客被拦截,审核未通过【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【社区】【博客】什么时候可以集成markdown编辑器
    【功能模块】【社区】【博客】什么时候可以集成markdown编辑器【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • 支持 markdown , 却不支持其他域名的图片
    那么如何在  markdown 下面, 复制图片进来呢 ?   选择了 markdown 结果还是要自己单张上传图片, 感觉这个限制很不人性化呀
  • [版主交流] Markdown编辑器 使用指南
    # 欢迎使用 Markdown 编辑器 您好!如果您想学习如何使用Markdown编辑器,可以仔细阅读这篇文章,了解Markdown的基本语法知识。 ## 功能快捷键 撤销:Ctrl/Command + Z 重做:Ctrl/Command + Y 加粗:Ctrl/Command + B 斜体:Ctrl/Command + I 标题:Ctrl/Command + Shift + H 无序列表:Ctrl/Command + Shift + U 有序列表:Ctrl/Command + Shift + O 检查列表:Ctrl/Command + Shift + C 代码:Ctrl/Command + Shift + K 链接:Ctrl/Command + Shift + L 图片:Ctrl/Command + Shift + G 查找:Ctrl/Command + F 替换:Ctrl/Command + G ## 如何改变文本的样式 **加粗文本**:`**加粗文本**` *倾斜文本*:`*倾斜文本*` 下划线:`下划线` >引用文本:`>引用文本` ## 如何添加链接 链接:[Markdown 使用指南](https://bbs.huaweicloud.com/forum/) ```md [Markdown 使用指南](https://bbs.huaweicloud.com/forum/) ``` ## 如何添加代码片 选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 `代码片`. ```java**Script** // An highlighted block var foo = 'bar'; ``` ## 如何添加列表 - 项目 - 项目 - 项目 ```md - 项目 - 项目 - 项目 ``` 1. 项目1 2. 项目2 3. 项目3 ```md 1. 项目1 2. 项目2 3. 项目3 ``` ## 如何创建表格 项目 | Value -------- | ----- 电脑 | $1600 手机 | $12 导管 | $1 ```md 项目 | Value -------- | ----- 电脑 | $1600 手机 | $12 导管 | $1 ``` 标题 4 | 标题 5 | 标题 6 ----- | ----- | ----- 文本 1 | 文本 2 | 文本 3 文本 1 | 文本 2 | 文本 3 ### 设定内容居中、居左、居右 使用`:---------:`居中 使用`:----------`居左 使用`----------:`居右 | 第一列 | 第二列 | 第三列 | |:-----------:| -------------:|:-------------| | 第一列文本居中 | 第二列文本居右 | 第三列文本居左 | ```md | 第一列 | 第二列 | 第三列 | |:-----------:| -------------:|:-------------| | 第一列文本居中 | 第二列文本居右 | 第三列文本居左 | ``` ## Markdow编辑器使用FAQ Q1:支持标记文本吗? A1:不支持标记文本,不支持对文本添加背景色; Q1:暂不支持的功能有哪些? A1:数学公式、自定义列表、甘特图、UML图、流程图、导入导出等增强功能一期暂不支持; Q1:markdown编辑器发布的帖子可以用富文本再编辑吗? A1:不可以,一篇帖子内容仅支持一种编辑器发布、再编辑; ## 结语 以上几种格式是比较常用的格式,针对这些语法做了说明;希望我们的指南可以帮助到您,在使用过程中如有疑问可跟帖咨询,将有技术专员为您解答。 注:[Markdown基本语法参考](https://www.jianshu.com/p/191d1e21f7ed)
  • [分享交流] 希望论坛尽快支持用Markdown语法写的笔记附件的上传
        想在论坛发布学习笔记,但是看到论坛上传附件那里并没有支持md后缀的,所以希望开发人员早点解决吧,像我身边的朋友好多都是用这个写笔记的,但是论坛不支持这个格式的,以上.
  • [互动交流] 代码托管服务,markdown不支持表格,这个不好用,建议支持通用的扩展能力。
    如题
总条数:56 到第
上滑加载中