新手问题 [已解决] 有没有关于项目如何使用 markdown 的简明教程?

chairy11 · 2014年08月09日 · 最后由 flowerwrong 回复于 2014年08月11日 · 2819 次阅读

问题

想在博客程序中用 markdown,琢磨半天。 看了 railscasts #272 Markdown with Redcarpet 看了篇博文Markdown 与 Redcarpet 简介 当然也看了redcarpet

上面看起来挺简单的。但再看 ruby-china 的源码,马上崩溃了……

#lib/markdown.rb,这个为什么这么多东西,为什么要放 lib 呢? #/lib/tasks/markdown_body.rake这个看不懂耶……什么时候用? #application_helper.rb这个能明白 #topics_helper.rb才是我的大问题,format_topic_body 到底用在哪里了?我没找到啊! 前面的帖子会说

<%= markdown(@article.content) %>

或者

class Blog < ActiveRecord::Base
  before_save :fill_html_content

  #将markup的content转换为html并写入字段
  def fill_html_content
    self.html_content = Klog::Markdown.render(self.content)
  end
end

但我没找到 ruby-china 里怎么发生的这一切啊…… 也没有别的一个完整的例子……

我的理解是:

  • 方案一:比如写文章,在 form 里填写 body 内容之后,先把 textarea 中的东西转换为 html,然后存入数据库,下次 show 中读取,直接就显示 html...
  • 方案二:比如写文章,在 form 里填写 body 内容之后,textarea 中的东西直接保存,存入数据库,下次 show 时,把这个字段的东西转换成 html...

额,没想明白…… 哇哇哇哇哇哇……我哭……

难道我要一辈子都呆在新手区吗?

解决方案

之前可能把事情想复杂了,我现在的理解是,照常保存,然后在 show.html.erb 中,使用了 markdown 格式的字段,就用 Redcarpet 转换为 html 就好了。

def markdown(text)
  renderer = Redcarpet::Render::HTML.new(filter_html:true, hard_wrap:true)
  markdown = Redcarpet::Markdown.new(renderer, fenced_code_blocks:true, autolink:true,space_after_headers:true,tables:true)
  syntax_highlighter(markdown.render(text)).html_safe
end

def syntax_highlighter(html)
  doc = Nokogiri::HTML(html)
  doc.search("//pre[@lang]").each do |pre|
    pre.replace Albino.colorize(pre.text.rstrip, pre[:lang])
  end
  doc.to_s
end

app/model/mongoid/markdown_body.rb的before_save :markdown_body

难道我要一辈子都呆在新手区吗?

BINGO!!!

使用 javascript 的 pagedown,类似 stackedit.io 的解决方案,还可以直接预览…

#5 楼 @bhuztez 切!那你跟着丢人,因为你算我半个师傅!

#5 楼 @bhuztez 切!那你跟着丢人,因为你算我半个师傅!

#5 楼 @bhuztez 切!那你跟着丢人,因为你算我半个师傅!

#3 楼 @flowerwrong 亲,你的 demo 看起来真的很简单,好高兴,你看我理解对不对哦:

  1. 数据库中存入的 content 字段,原是 text 类型,而实际存入的是含 html 的内容。所以 show.html.erb 中,直接用 <%= @article.content %> 就行了。
  2. 而在填写 form 时候,写入 content 列的本来是 markdown 格式的内容,这时候就要用 Redcarpet 提供的方法,把 markdown 格式内容转换为 html 内容,你是在 create 中写的。(那我想到,update 的时候呢?不也要用这个方法吗?呀,我这样想是不是不对?)

#10 楼 @chairy11 update 里面的我没写,但是除了 content 字段保存 html 内容外,还有一个 markdown 字段保存 markdown 原格式。所以

def update
  @article = Article.find(params[:id])
  markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true, fenced_code_blocks: true)
  html_content = markdown.render(article_params[:markdown])
  @article.content = html_content
  @article.markdown = article_params[:markdown]
  respond_to do |format|
    if @article.save
      format.html { redirect_to @article, notice: 'Article was successfully updated.' }
      format.json { render :show, status: :ok, location: @article }
    else
      format.html { render :edit }
      format.json { render json: @article.errors, status: :unprocessable_entity }
    end
  end
end

就 ok 了。喔,对了,markdown 实例可以用单例模式。这里就省了。

#11 楼 @flowerwrong 如果你的 content 和 markdown 两个字段,本来是同一个东西的内容,只是一种是 html 格式,一种是原来的 markdown 格式,那是不是不太好?违反 DRY 格式什么的……而在 edit 的时候,又怎么处理呢? 是不是应该有个转换机制,自由地把在 markdown 格式和 html 中转换?

呀,没想明白……

#2 楼 @cassiuschen 小帅哥,请原谅我 IQ 只有 30.

#11 楼 @flowerwrong 我忽然觉得,咱们想复杂了……其实就是原来是怎么写的就怎么存入数据库,然后在 show.html.erb 里面,把读出来的 markdown 格式转换为 html 格式就行了……

#14 楼 @chairy11 每次解析 md 会耗费资源

#15 楼 @flowerwrong 缓存呢?可以的不? 反正我决定怎么简单怎么来,貌似已经弄好了

def markdown(text)
  renderer = Redcarpet::Render::HTML.new(filter_html:true, hard_wrap:true)
  markdown = Redcarpet::Markdown.new(renderer, fenced_code_blocks:true, autolink:true,space_after_headers:true,tables:true)
  syntax_highlighter(markdown.render(text)).html_safe
end

def syntax_highlighter(html)
  doc = Nokogiri::HTML(html)
  doc.search("//pre[@lang]").each do |pre|
    pre.replace Albino.colorize(pre.text.rstrip, pre[:lang])
  end
  doc.to_s
end

#16 楼 @chairy11 嗯,使用缓存更好。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号