summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Allen <dan.j.allen@gmail.com>2022-07-05 01:55:45 -0600
committerGitHub <noreply@github.com>2022-07-05 01:55:45 -0600
commit7822fbe9223ca81e9895f6132b2274e89f26c623 (patch)
tree634d315adf29cfe5df18647d2e87fffe7afb67de /lib
parent3c575b9de21790d3b812c74948c42eb6470ec02b (diff)
resolves #4306 disallow the use of the left square bracket in an attribute list on formatted text (PR #4307)
Diffstat (limited to 'lib')
-rw-r--r--lib/asciidoctor.rb36
-rw-r--r--lib/asciidoctor/rx.rb6
2 files changed, 22 insertions, 20 deletions
diff --git a/lib/asciidoctor.rb b/lib/asciidoctor.rb
index 581c8647..45c28f6a 100644
--- a/lib/asciidoctor.rb
+++ b/lib/asciidoctor.rb
@@ -436,6 +436,8 @@ module Asciidoctor
CC_WORD = CG_WORD = '\p{Word}'
end
+ QuoteAttributeListRxt = %(\\[([^\\[\\]]+)\\])
+
QUOTE_SUBS = {}.tap do |accum|
# unconstrained quotes:: can appear anywhere
# constrained quotes:: must be bordered by non-word characters
@@ -443,46 +445,46 @@ module Asciidoctor
# the order in which they are replaced is important
accum[false] = normal = [
# **strong**
- [:strong, :unconstrained, /\\?(?:\[([^\]]+)\])?\*\*(#{CC_ALL}+?)\*\*/m],
+ [:strong, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?\*\*(#{CC_ALL}+?)\*\*/m],
# *strong*
- [:strong, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?\*(\S|\S#{CC_ALL}*?\S)\*(?!#{CG_WORD})/m],
+ [:strong, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?\*(\S|\S#{CC_ALL}*?\S)\*(?!#{CG_WORD})/m],
# "`double-quoted`"
- [:double, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?"`(\S|\S#{CC_ALL}*?\S)`"(?!#{CG_WORD})/m],
+ [:double, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?"`(\S|\S#{CC_ALL}*?\S)`"(?!#{CG_WORD})/m],
# '`single-quoted`'
- [:single, :constrained, /(^|[^#{CC_WORD};:`}])(?:\[([^\]]+)\])?'`(\S|\S#{CC_ALL}*?\S)`'(?!#{CG_WORD})/m],
+ [:single, :constrained, /(^|[^#{CC_WORD};:`}])(?:#{QuoteAttributeListRxt})?'`(\S|\S#{CC_ALL}*?\S)`'(?!#{CG_WORD})/m],
# ``monospaced``
- [:monospaced, :unconstrained, /\\?(?:\[([^\]]+)\])?``(#{CC_ALL}+?)``/m],
+ [:monospaced, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?``(#{CC_ALL}+?)``/m],
# `monospaced`
- [:monospaced, :constrained, /(^|[^#{CC_WORD};:"'`}])(?:\[([^\]]+)\])?`(\S|\S#{CC_ALL}*?\S)`(?![#{CC_WORD}"'`])/m],
+ [:monospaced, :constrained, /(^|[^#{CC_WORD};:"'`}])(?:#{QuoteAttributeListRxt})?`(\S|\S#{CC_ALL}*?\S)`(?![#{CC_WORD}"'`])/m],
# __emphasis__
- [:emphasis, :unconstrained, /\\?(?:\[([^\]]+)\])?__(#{CC_ALL}+?)__/m],
+ [:emphasis, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?__(#{CC_ALL}+?)__/m],
# _emphasis_
- [:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?_(\S|\S#{CC_ALL}*?\S)_(?!#{CG_WORD})/m],
+ [:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?_(\S|\S#{CC_ALL}*?\S)_(?!#{CG_WORD})/m],
# ##mark## (referred to in AsciiDoc.py as unquoted)
- [:mark, :unconstrained, /\\?(?:\[([^\]]+)\])?##(#{CC_ALL}+?)##/m],
+ [:mark, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?##(#{CC_ALL}+?)##/m],
# #mark# (referred to in AsciiDoc.py as unquoted)
- [:mark, :constrained, /(^|[^#{CC_WORD}&;:}])(?:\[([^\]]+)\])?#(\S|\S#{CC_ALL}*?\S)#(?!#{CG_WORD})/m],
+ [:mark, :constrained, /(^|[^#{CC_WORD}&;:}])(?:#{QuoteAttributeListRxt})?#(\S|\S#{CC_ALL}*?\S)#(?!#{CG_WORD})/m],
# ^superscript^
- [:superscript, :unconstrained, /\\?(?:\[([^\]]+)\])?\^(\S+?)\^/],
+ [:superscript, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?\^(\S+?)\^/],
# ~subscript~
- [:subscript, :unconstrained, /\\?(?:\[([^\]]+)\])?~(\S+?)~/],
+ [:subscript, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?~(\S+?)~/],
]
accum[true] = compat = normal.drop 0
# ``quoted''
- compat[2] = [:double, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?``(\S|\S#{CC_ALL}*?\S)''(?!#{CG_WORD})/m]
+ compat[2] = [:double, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?``(\S|\S#{CC_ALL}*?\S)''(?!#{CG_WORD})/m]
# `quoted'
- compat[3] = [:single, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?`(\S|\S#{CC_ALL}*?\S)'(?!#{CG_WORD})/m]
+ compat[3] = [:single, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?`(\S|\S#{CC_ALL}*?\S)'(?!#{CG_WORD})/m]
# ++monospaced++
- compat[4] = [:monospaced, :unconstrained, /\\?(?:\[([^\]]+)\])?\+\+(#{CC_ALL}+?)\+\+/m]
+ compat[4] = [:monospaced, :unconstrained, /\\?(?:#{QuoteAttributeListRxt})?\+\+(#{CC_ALL}+?)\+\+/m]
# +monospaced+
- compat[5] = [:monospaced, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?\+(\S|\S#{CC_ALL}*?\S)\+(?!#{CG_WORD})/m]
+ compat[5] = [:monospaced, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?\+(\S|\S#{CC_ALL}*?\S)\+(?!#{CG_WORD})/m]
# #unquoted#
#compat[8] = [:unquoted, *compat[8][1..-1]]
# ##unquoted##
#compat[9] = [:unquoted, *compat[9][1..-1]]
# 'emphasis'
- compat.insert 3, [:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:\[([^\]]+)\])?'(\S|\S#{CC_ALL}*?\S)'(?!#{CG_WORD})/m]
+ compat.insert 3, [:emphasis, :constrained, /(^|[^#{CC_WORD};:}])(?:#{QuoteAttributeListRxt})?'(\S|\S#{CC_ALL}*?\S)'(?!#{CG_WORD})/m]
end
# NOTE order of replacements is significant
diff --git a/lib/asciidoctor/rx.rb b/lib/asciidoctor/rx.rb
index 6cc378ea..5e73b13f 100644
--- a/lib/asciidoctor/rx.rb
+++ b/lib/asciidoctor/rx.rb
@@ -573,8 +573,8 @@ module Asciidoctor
#
# NOTE we always capture the attributes so we know when to use compatible (i.e., legacy) behavior
InlinePassRx = {
- false => ['+', '`', /(^|[^#{CC_WORD};:])(?:\[([^\]]+)\])?(\\?(\+|`)(\S|\S#{CC_ALL}*?\S)\4)(?!#{CG_WORD})/m],
- true => ['`', nil, /(^|[^`#{CC_WORD}])(?:\[([^\]]+)\])?(\\?(`)([^`\s]|[^`\s]#{CC_ALL}*?\S)\4)(?![`#{CC_WORD}])/m],
+ false => ['+', '`', /(^|[^#{CC_WORD};:])(?:#{QuoteAttributeListRxt})?(\\?(\+|`)(\S|\S#{CC_ALL}*?\S)\4)(?!#{CG_WORD})/m],
+ true => ['`', nil, /(^|[^`#{CC_WORD}])(?:#{QuoteAttributeListRxt})?(\\?(`)([^`\s]|[^`\s]#{CC_ALL}*?\S)\4)(?![`#{CC_WORD}])/m],
}
# Matches an inline plus passthrough spanning multiple lines, but only when it occurs directly
@@ -595,7 +595,7 @@ module Asciidoctor
# pass:quotes[text]
#
# NOTE we have to support an empty pass:[] for compatibility with AsciiDoc.py
- InlinePassMacroRx = /(?:(?:(\\?)\[([^\]]+)\])?(\\{0,2})(\+\+\+?|\$\$)(#{CC_ALL}*?)\4|(\\?)pass:([a-z]+(?:,[a-z-]+)*)?\[(|#{CC_ALL}*?[^\\])\])/m
+ InlinePassMacroRx = /(?:(?:(\\?)#{QuoteAttributeListRxt})?(\\{0,2})(\+\+\+?|\$\$)(#{CC_ALL}*?)\4|(\\?)pass:([a-z]+(?:,[a-z-]+)*)?\[(|#{CC_ALL}*?[^\\])\])/m
# Matches an xref (i.e., cross-reference) inline macro, which may span multiple lines.
#