mirror of
https://github.com/yuin/goldmark
synced 2025-03-04 23:04:52 +00:00
Define EastAsianLineBreaksStyle to specify behavior of line breaking
This commit is contained in:
parent
dc2230c235
commit
9d0b1b6bb8
3 changed files with 75 additions and 60 deletions
|
|
@ -9,31 +9,31 @@ import (
|
|||
// A CJKOption sets options for CJK support mostly for HTML based renderers.
|
||||
type CJKOption func(*cjk)
|
||||
|
||||
// A EastAsianLineBreaksOption sets options for east asian line breaks.
|
||||
type EastAsianLineBreaksOption func(*eastAsianLineBreaks)
|
||||
// A EastAsianLineBreaksStyle is a style of east asian line breaks.
|
||||
type EastAsianLineBreaksStyle int
|
||||
|
||||
const (
|
||||
EastAsianLineBreaksStyleSimple EastAsianLineBreaksStyle = iota
|
||||
EastAsianLineBreaksCSS3Draft
|
||||
)
|
||||
|
||||
type EastAsianLineBreaksFunction func()
|
||||
|
||||
// WithEastAsianLineBreaks is a functional option that indicates whether softline breaks
|
||||
// between east asian wide characters should be ignored.
|
||||
func WithEastAsianLineBreaks(opts ...EastAsianLineBreaksOption) CJKOption {
|
||||
func WithEastAsianLineBreaks(style ...EastAsianLineBreaksStyle) CJKOption {
|
||||
return func(c *cjk) {
|
||||
e := &eastAsianLineBreaks{
|
||||
Enabled: true,
|
||||
EastAsianLineBreaksStyle: EastAsianLineBreaksStyleSimple,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(e)
|
||||
for _, s := range style {
|
||||
e.EastAsianLineBreaksStyle = s
|
||||
}
|
||||
c.EastAsianLineBreaks = e
|
||||
}
|
||||
}
|
||||
|
||||
// WithWorksEvenWithOneSide is a functional option that indicates that a softline break
|
||||
// is ignored even if only one side of the break is east asian wide character.
|
||||
func WithWorksEvenWithOneSide() EastAsianLineBreaksOption {
|
||||
return func(e *eastAsianLineBreaks) {
|
||||
e.WorksEvenWithOneSide = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithEscapedSpace is a functional option that indicates that a '\' escaped half-space(0x20) should not be rendered.
|
||||
func WithEscapedSpace() CJKOption {
|
||||
return func(c *cjk) {
|
||||
|
|
@ -48,7 +48,7 @@ type cjk struct {
|
|||
|
||||
type eastAsianLineBreaks struct {
|
||||
Enabled bool
|
||||
WorksEvenWithOneSide bool
|
||||
EastAsianLineBreaksStyle EastAsianLineBreaksStyle
|
||||
}
|
||||
|
||||
// CJK is a goldmark extension that provides functionalities for CJK languages.
|
||||
|
|
@ -66,13 +66,13 @@ func NewCJK(opts ...CJKOption) goldmark.Extender {
|
|||
func (e *cjk) Extend(m goldmark.Markdown) {
|
||||
if e.EastAsianLineBreaks != nil {
|
||||
if e.EastAsianLineBreaks.Enabled {
|
||||
opts := []html.EastAsianLineBreaksOption{}
|
||||
if e.EastAsianLineBreaks.WorksEvenWithOneSide {
|
||||
opts = append(opts, html.WithWorksEvenWithOneSide())
|
||||
style := html.EastAsianLineBreaksStyleSimple
|
||||
switch e.EastAsianLineBreaks.EastAsianLineBreaksStyle {
|
||||
case EastAsianLineBreaksCSS3Draft:
|
||||
style = html.EastAsianLineBreaksCSS3Draft
|
||||
}
|
||||
m.Renderer().AddOptions(html.WithEastAsianLineBreaks(opts...))
|
||||
m.Renderer().AddOptions(html.WithEastAsianLineBreaks(style))
|
||||
}
|
||||
|
||||
}
|
||||
if e.EscapedSpace {
|
||||
m.Renderer().AddOptions(html.WithWriter(html.NewWriter(html.WithEscapedSpace())))
|
||||
|
|
|
|||
|
|
@ -209,13 +209,13 @@ func TestEastAsianLineBreaks(t *testing.T) {
|
|||
t,
|
||||
)
|
||||
|
||||
// WithWorksEvenWithOneSide option
|
||||
// test with EastAsianLineBreaksCSS3Draft
|
||||
markdown = goldmark.New(goldmark.WithRendererOptions(
|
||||
html.WithXHTML(),
|
||||
html.WithUnsafe(),
|
||||
),
|
||||
goldmark.WithExtensions(
|
||||
NewCJK(WithEastAsianLineBreaks(WithWorksEvenWithOneSide())),
|
||||
NewCJK(WithEastAsianLineBreaks(EastAsianLineBreaksCSS3Draft)),
|
||||
),
|
||||
)
|
||||
no = 9
|
||||
|
|
|
|||
|
|
@ -103,52 +103,75 @@ func WithHardWraps() interface {
|
|||
// EastAsianLineBreaks is an option name used in WithEastAsianLineBreaks.
|
||||
const optEastAsianLineBreaks renderer.OptionName = "EastAsianLineBreaks"
|
||||
|
||||
type EastAsianLineBreaksStyle int
|
||||
|
||||
const (
|
||||
EastAsianLineBreaksStyleSimple EastAsianLineBreaksStyle = iota
|
||||
EastAsianLineBreaksCSS3Draft
|
||||
)
|
||||
|
||||
type eastAsianLineBreaksFunction interface {
|
||||
SoftLineBreak(thisLastRune rune, siblingFirstRune rune) bool
|
||||
}
|
||||
|
||||
type eastAsianLineBreaksSimple struct{}
|
||||
|
||||
func (e *eastAsianLineBreaksSimple) SoftLineBreak(thisLastRune rune, siblingFirstRune rune) bool {
|
||||
return !(util.IsEastAsianWideRune(thisLastRune) && util.IsEastAsianWideRune(siblingFirstRune))
|
||||
}
|
||||
|
||||
type eastAsianLineBreaksCSS3Draft struct{}
|
||||
|
||||
func (e *eastAsianLineBreaksCSS3Draft) SoftLineBreak(thisLastRune rune, siblingFirstRune rune) bool {
|
||||
return !(util.IsEastAsianWideRune(thisLastRune) || util.IsEastAsianWideRune(siblingFirstRune))
|
||||
}
|
||||
|
||||
type eastAsianLineBreaks struct {
|
||||
Enabled bool
|
||||
WorksEvenWithOneSide bool
|
||||
EastAsianLineBreaksFunction eastAsianLineBreaksFunction
|
||||
}
|
||||
|
||||
type withEastAsianLineBreaks struct {
|
||||
worksEvenWithOneSide bool
|
||||
eastAsianLineBreaksStyle EastAsianLineBreaksStyle
|
||||
}
|
||||
|
||||
// A EastAsianLineBreaksOption sets options for east asian line breaks.
|
||||
type EastAsianLineBreaksOption func(*withEastAsianLineBreaks)
|
||||
|
||||
func (o *withEastAsianLineBreaks) SetConfig(c *renderer.Config) {
|
||||
switch o.eastAsianLineBreaksStyle {
|
||||
case EastAsianLineBreaksStyleSimple:
|
||||
c.Options[optEastAsianLineBreaks] = eastAsianLineBreaks{
|
||||
Enabled: true,
|
||||
WorksEvenWithOneSide: o.worksEvenWithOneSide,
|
||||
EastAsianLineBreaksFunction: &eastAsianLineBreaksSimple{},
|
||||
}
|
||||
case EastAsianLineBreaksCSS3Draft:
|
||||
c.Options[optEastAsianLineBreaks] = eastAsianLineBreaks{
|
||||
Enabled: true,
|
||||
EastAsianLineBreaksFunction: &eastAsianLineBreaksCSS3Draft{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *withEastAsianLineBreaks) SetHTMLOption(c *Config) {
|
||||
switch o.eastAsianLineBreaksStyle {
|
||||
case EastAsianLineBreaksStyleSimple:
|
||||
c.EastAsianLineBreaks = eastAsianLineBreaks{
|
||||
Enabled: true,
|
||||
WorksEvenWithOneSide: o.worksEvenWithOneSide,
|
||||
EastAsianLineBreaksFunction: &eastAsianLineBreaksSimple{},
|
||||
}
|
||||
case EastAsianLineBreaksCSS3Draft:
|
||||
c.EastAsianLineBreaks = eastAsianLineBreaks{
|
||||
Enabled: true,
|
||||
EastAsianLineBreaksFunction: &eastAsianLineBreaksCSS3Draft{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithEastAsianLineBreaks is a functional option that indicates whether softline breaks
|
||||
// between east asian wide characters should be ignored.
|
||||
func WithEastAsianLineBreaks(opts ...EastAsianLineBreaksOption) interface {
|
||||
func WithEastAsianLineBreaks(style EastAsianLineBreaksStyle) interface {
|
||||
renderer.Option
|
||||
Option
|
||||
} {
|
||||
w := &withEastAsianLineBreaks{}
|
||||
for _, opt := range opts {
|
||||
opt(w)
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
// WithWorksEvenWithOneSide is a functional option that indicates that a softline break
|
||||
// is ignored even if only one side of the break is east asian wide character.
|
||||
func WithWorksEvenWithOneSide() EastAsianLineBreaksOption {
|
||||
return func(o *withEastAsianLineBreaks) {
|
||||
o.worksEvenWithOneSide = true
|
||||
}
|
||||
return &withEastAsianLineBreaks{style}
|
||||
}
|
||||
|
||||
// XHTML is an option name used in WithXHTML.
|
||||
|
|
@ -697,17 +720,9 @@ func (r *Renderer) renderText(w util.BufWriter, source []byte, node ast.Node, en
|
|||
if siblingText := sibling.(*ast.Text).Text(source); len(siblingText) != 0 {
|
||||
thisLastRune := util.ToRune(value, len(value)-1)
|
||||
siblingFirstRune, _ := utf8.DecodeRune(siblingText)
|
||||
if r.EastAsianLineBreaks.WorksEvenWithOneSide {
|
||||
if !(util.IsEastAsianWideRune(thisLastRune) ||
|
||||
util.IsEastAsianWideRune(siblingFirstRune)) {
|
||||
if r.EastAsianLineBreaks.EastAsianLineBreaksFunction.SoftLineBreak(thisLastRune, siblingFirstRune) {
|
||||
_ = w.WriteByte('\n')
|
||||
}
|
||||
} else {
|
||||
if !(util.IsEastAsianWideRune(thisLastRune) &&
|
||||
util.IsEastAsianWideRune(siblingFirstRune)) {
|
||||
_ = w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue