1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/rdoc/parser/changelog.rb
nagachika 2a70d21484 merge revision(s) b1c73f239fe9af97de837331849f55d67c27561e,bb570ce6d80d28cfc7131dcb72885eed2f989b30,b88d1e6b44164bca0c2b85ea6639469813e1e1d8,127f735c1e5e0771076caf2a74390757a42fb177,f3f1a666c77f8c528b0adc9ccf78e4b9910bd6e0,fa048a0f8523cefde5428805dd334691486319e6,d5d1c41728d65acfb8aa2cf95f2d8ac88f271cd1,52ebaf718e6a78297ceb0dff49815eeed28eae45,7fe22152fc28084f4395fece84ff6e5eb2d6b288,19e6d271266eca5925e66fc8ec39b251a2fa6bcd,05898c5b9001c0b1e8bd7bf0d12b42a8e7c388b8,3651f678a719ae3a35825bcb4e0dabbc7c60d8df,10b082064e6ab0943cce4ef43e567d8044c7096d,de8e6218a3257fe19b46ff0aa157e66f452ac8b7,971a0cd246db6578e1ea8760a903e1a23e3681f3,61a29a41e1d0d11a9963315aa86d25ed690124c0,ff9a00887161840eb8a34d53749a7d7962181cfe,fad3412d475b57055f426cf4e86eafeab516672b,54aa11efa8b1be2c5d20402890d6d2fa90aa19a8,e84d275fe6d0c14ba58ce73b13323879c060b7ae,61e1cf23ac0d122fba3ad4cbaa402c7c94ad54d3,a6948329f8f89fb390215086fe4a888915fd589e,64b991b0cd98ee8f23266b8cbea0fa34bdaab1ec,b1c73f239fe9af97de837331849f55d67c27561e,0ee24b4fab1a1faef600a42c29863e1c3edd8c61: [Backport #17877]
Synchronize rdoc with upstream version v6.3.1.

	[ruby/rdoc] Use File.open to fix the OS Command Injection
	 vulnerability in CVE-2021-31799

	a7f5d6ab88
	---
	 lib/rdoc/rdoc.rb            |  2 +-
	 test/rdoc/test_rdoc_rdoc.rb | 12 ++++++++++++
	 2 files changed, 13 insertions(+), 1 deletion(-)

	[ruby/rdoc] Support ChangeLog generated by `git log`

	5e0a123ca1
	---
	 lib/rdoc/parser/changelog.rb            | 35 +++++++++++++++++++++
	 test/rdoc/test_rdoc_parser_changelog.rb | 56 +++++++++++++++++++++++++++++++++
	 2 files changed, 91 insertions(+)

	[ruby/rdoc] Make each commit entries h3

	11eefb2ae9
	---
	 lib/rdoc/parser/changelog.rb            | 12 ++++++------
	 test/rdoc/test_rdoc_parser_changelog.rb | 12 ++++--------
	 2 files changed, 10 insertions(+), 14 deletions(-)

	[ruby/rdoc] Tweak log entry markdown

	* add 3 levels to headings
	* prefix commit log to labels to make unique IDs

	5074c13209
	---
	 lib/rdoc/parser/changelog.rb            | 20 +++++++++++++++++-
	 test/rdoc/test_rdoc_parser_changelog.rb | 36 ++++++++++++++++++++++++++++++++-
	 2 files changed, 54 insertions(+), 2 deletions(-)

	[ruby/rdoc] Shorten commit hashes

	5d3e153963
	---
	 lib/rdoc/parser/changelog.rb            | 2 +-
	 test/rdoc/test_rdoc_parser_changelog.rb | 2 +-
	 2 files changed, 2 insertions(+), 2 deletions(-)

	[ruby/rdoc] Add links to the commits

	1821628076
	---
	 lib/rdoc/parser/changelog.rb            | 107 +++++++++++++++++++++++++-------
	 test/rdoc/test_rdoc_parser_changelog.rb |  36 ++++++-----
	 2 files changed, 107 insertions(+), 36 deletions(-)

	[ruby/rdoc] Sort by CommitDate if available

	455715e930
	---
	 lib/rdoc/parser/changelog.rb            | 11 ++++++---
	 test/rdoc/test_rdoc_parser_changelog.rb | 40 +++++++++++++++++++++++++++++++++
	 2 files changed, 48 insertions(+), 3 deletions(-)

	[ruby/rdoc] Skip non-date logs by git-log

	`RDoc::Parser::ChangeLog` mis-parses ChangeLog generated by
	git-log, because of too heuristic `Time.parse`.

	For instance, "commit 8187228de0"
	results in "8187-08-16", that is, day 228 in the year 8187.

	9711e6f6d9
	---
	 lib/rdoc/parser/changelog.rb            | 36 ++++++++++++++++++++-------------
	 test/rdoc/test_rdoc_parser_changelog.rb |  2 ++
	 2 files changed, 24 insertions(+), 14 deletions(-)

	[ruby/rdoc] Support other date formats in git-log

	ad8cf37d72
	---
	 lib/rdoc/parser/changelog.rb            |  6 +++---
	 test/rdoc/test_rdoc_parser_changelog.rb | 22 ++++++++++++++++++++++
	 2 files changed, 25 insertions(+), 3 deletions(-)

	[ruby/rdoc] Support iso-strict format in git-log

	2a6c22da63
	---
	 lib/rdoc/parser/changelog.rb            |  6 +++---
	 test/rdoc/test_rdoc_parser_changelog.rb | 11 +++++++++++
	 2 files changed, 14 insertions(+), 3 deletions(-)

	[ruby/rdoc] Update Rdoc.css sidebar panel.

	Updates css so the sidebar look like a panel instead of looking like chopped edges.

	b0098c6d72
	---
	 lib/rdoc/generator/template/darkfish/css/rdoc.css | 1 +
	 1 file changed, 1 insertion(+)

	[ruby/rdoc] Support GFM table

	9dc933df16
	---
	 lib/rdoc/markdown.rb                    | 349 +++++++++++++++++++++++++++++++-
	 lib/rdoc/markup.rb                      |   1 +
	 lib/rdoc/markup/table.rb                |  47 +++++
	 lib/rdoc/markup/to_html.rb              |  23 +++
	 lib/rdoc/markup/to_joined_paragraph.rb  |   1 +
	 lib/rdoc/markup/to_rdoc.rb              |  28 +++
	 lib/rdoc/markup/to_table_of_contents.rb |   1 +
	 test/rdoc/test_rdoc_markdown.rb         |  23 +++
	 8 files changed, 471 insertions(+), 2 deletions(-)
	 create mode 100644 lib/rdoc/markup/table.rb

	[ruby/rdoc] Add table style

	2219c5ae80
	---
	 lib/rdoc/generator/template/darkfish/css/rdoc.css | 19 +++++++++++++++++++
	 1 file changed, 19 insertions(+)

	[ruby/rdoc] Fixed CodeFence without blank lines

	Currently a fenced code block needs a preceding blank line, it
	should not be required, as:
	https://github.github.com/gfm/#fenced-code-blocks
	> A fenced code block may interrupt a paragraph, and does not
	> require a blank line either before or after.

	Just recommended:
	https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks
	> We recommend placing a blank line before and after code blocks
	> to make the raw formatting easier to read.

	0e1776caf3
	---
	 lib/rdoc/markdown.rb            | 447 +++++++---------------------------------
	 test/rdoc/test_rdoc_markdown.rb |  36 +++-
	 2 files changed, 112 insertions(+), 371 deletions(-)

	[ruby/rdoc] Allow partial default values to be overridden with
	 .rdoc_options

	e14800891f
	---
	 lib/rdoc/options.rb         | 34 +++++++++++++++++++++++++++++++++-
	 lib/rdoc/rdoc.rb            |  7 ++++++-
	 test/rdoc/test_rdoc_rdoc.rb | 12 ++++++++++++
	 3 files changed, 51 insertions(+), 2 deletions(-)

	[ruby/rdoc] Allow empty .rdoc_options

	0c8cb25b50
	---
	 lib/rdoc/rdoc.rb            |  2 ++
	 test/rdoc/test_rdoc_rdoc.rb | 11 +++++++++++
	 2 files changed, 13 insertions(+)

	[ruby/rdoc] Suppress unused variable warning of "text"

	3a4120b155
	---
	 lib/rdoc/markdown.rb | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++-
	 1 file changed, 343 insertions(+), 2 deletions(-)

	[ruby/rdoc] Get rid of a trailing space

	7b7b91768e
	---
	 lib/rdoc/markdown.rb | 7 +++----
	 1 file changed, 3 insertions(+), 4 deletions(-)

	[ruby/rdoc] Disable other notations in <code> tags

	0cd3b55210
	---
	 lib/rdoc/markup/attr_span.rb                    |  10 ++-
	 lib/rdoc/markup/attribute_manager.rb            | 102 ++++++++++++++++++------
	 test/rdoc/test_rdoc_markup_attribute_manager.rb |  24 +++++-
	 test/rdoc/test_rdoc_markup_to_html.rb           |   6 ++
	 4 files changed, 114 insertions(+), 28 deletions(-)

	[ruby/rdoc] Treat other tags as word boundaries

	8222f85a17
	---
	 lib/rdoc/markup/attribute_manager.rb  | 17 +++++++++++++----
	 test/rdoc/test_rdoc_markup_to_html.rb |  5 +++++
	 2 files changed, 18 insertions(+), 4 deletions(-)

	[ruby/rdoc] Treat emphasis tags as excluding other notations

	And exclusive notations don't exclude other exclusive notations.

	b8baa9a435
	---
	 lib/rdoc/markup/attr_span.rb                    |  2 +-
	 lib/rdoc/markup/attribute_manager.rb            | 10 +++++-----
	 test/rdoc/test_rdoc_markup_attribute_manager.rb |  1 +
	 3 files changed, 7 insertions(+), 6 deletions(-)

	[ruby/rdoc] Clarify that dots in URL are replaced

	The dots in all path components from the document root are
	replaced with underscores, not only in the basename.

	7a3417ea4c
	---
	 test/rdoc/test_rdoc_top_level.rb | 3 +++
	 1 file changed, 3 insertions(+)

	[ruby/rdoc] Links to document texts without "rdoc-ref:" prefix

	While links to generated HTML from RDoc file needs to be prefixed
	by "rdoc-ref:" currently, in case of explicit references this
	seems just redundant.

	Also GitHub RDoc support does not work with this prefix.

	This patch lets links to such document texts (".rb", ".rdoc" and
	".md" now) refer URLs generated by `RDoc::TopLevel#http_url`
	without the prefix.

	f18b27b69d
	---
	 lib/rdoc/markup/to_html.rb            |  4 ++++
	 test/rdoc/test_rdoc_markup_to_html.rb | 21 +++++++++++++++++++++
	 2 files changed, 25 insertions(+)

	[ruby/rdoc] Use File.open to fix the OS Command Injection
	 vulnerability in CVE-2021-31799

	a7f5d6ab88
	---
	 lib/rdoc/rdoc.rb            |  2 +-
	 test/rdoc/test_rdoc_rdoc.rb | 12 ++++++++++++
	 2 files changed, 13 insertions(+), 1 deletion(-)

	[ruby/rdoc] Version 6.3.1

	9307f932b7
	---
	 lib/rdoc/version.rb | 2 +-
	 1 file changed, 1 insertion(+), 1 deletion(-)
2021-05-22 14:51:55 +09:00

335 lines
8.3 KiB
Ruby

# frozen_string_literal: true
##
# A ChangeLog file parser.
#
# This parser converts a ChangeLog into an RDoc::Markup::Document. When
# viewed as HTML a ChangeLog page will have an entry for each day's entries in
# the sidebar table of contents.
#
# This parser is meant to parse the MRI ChangeLog, but can be used to parse any
# {GNU style Change
# Log}[http://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html].
class RDoc::Parser::ChangeLog < RDoc::Parser
include RDoc::Parser::Text
parse_files_matching(/(\/|\\|\A)ChangeLog[^\/\\]*\z/)
##
# Attaches the +continuation+ of the previous line to the +entry_body+.
#
# Continued function listings are joined together as a single entry.
# Continued descriptions are joined to make a single paragraph.
def continue_entry_body entry_body, continuation
return unless last = entry_body.last
if last =~ /\)\s*\z/ and continuation =~ /\A\(/ then
last.sub!(/\)\s*\z/, ',')
continuation = continuation.sub(/\A\(/, '')
end
if last =~ /\s\z/ then
last << continuation
else
last << ' ' + continuation
end
end
##
# Creates an RDoc::Markup::Document given the +groups+ of ChangeLog entries.
def create_document groups
doc = RDoc::Markup::Document.new
doc.omit_headings_below = 2
doc.file = @top_level
doc << RDoc::Markup::Heading.new(1, File.basename(@file_name))
doc << RDoc::Markup::BlankLine.new
groups.sort_by do |day,| day end.reverse_each do |day, entries|
doc << RDoc::Markup::Heading.new(2, day.dup)
doc << RDoc::Markup::BlankLine.new
doc.concat create_entries entries
end
doc
end
##
# Returns a list of ChangeLog entries an RDoc::Markup nodes for the given
# +entries+.
def create_entries entries
out = []
entries.each do |entry, items|
out << RDoc::Markup::Heading.new(3, entry)
out << RDoc::Markup::BlankLine.new
out << create_items(items)
end
out
end
##
# Returns an RDoc::Markup::List containing the given +items+ in the
# ChangeLog
def create_items items
list = RDoc::Markup::List.new :NOTE
items.each do |item|
item =~ /\A(.*?(?:\([^)]+\))?):\s*/
title = $1
body = $'
paragraph = RDoc::Markup::Paragraph.new body
list_item = RDoc::Markup::ListItem.new title, paragraph
list << list_item
end
list
end
##
# Groups +entries+ by date.
def group_entries entries
@time_cache ||= {}
entries.group_by do |title, _|
begin
time = @time_cache[title]
(time || parse_date(title)).strftime '%Y-%m-%d'
rescue NoMethodError, ArgumentError
time, = title.split ' ', 2
parse_date(time).strftime '%Y-%m-%d'
end
end
end
##
# Parse date in ISO-8601, RFC-2822, or default of Git
def parse_date(date)
case date
when /\A\s*(\d+)-(\d+)-(\d+)(?:[ T](\d+):(\d+):(\d+) *([-+]\d\d):?(\d\d))?\b/
Time.new($1, $2, $3, $4, $5, $6, ("#{$7}:#{$8}" if $7))
when /\A\s*\w{3}, +(\d+) (\w{3}) (\d+) (\d+):(\d+):(\d+) *(?:([-+]\d\d):?(\d\d))\b/
Time.new($3, $2, $1, $4, $5, $6, ("#{$7}:#{$8}" if $7))
when /\A\s*\w{3} (\w{3}) +(\d+) (\d+) (\d+):(\d+):(\d+) *(?:([-+]\d\d):?(\d\d))\b/
Time.new($3, $1, $2, $4, $5, $6, ("#{$7}:#{$8}" if $7))
when /\A\s*\w{3} (\w{3}) +(\d+) (\d+):(\d+):(\d+) (\d+)\b/
Time.new($6, $1, $2, $3, $4, $5)
else
raise ArgumentError, "bad date: #{date}"
end
end
##
# Parses the entries in the ChangeLog.
#
# Returns an Array of each ChangeLog entry in order of parsing.
#
# A ChangeLog entry is an Array containing the ChangeLog title (date and
# committer) and an Array of ChangeLog items (file and function changed with
# description).
#
# An example result would be:
#
# [ 'Tue Dec 4 08:33:46 2012 Eric Hodel <drbrain@segment7.net>',
# [ 'README.EXT: Converted to RDoc format',
# 'README.EXT.ja: ditto']]
def parse_entries
@time_cache ||= {}
if /\A((?:.*\n){,3})commit\s/ =~ @content
class << self; prepend Git; end
parse_info($1)
return parse_entries
end
entries = []
entry_name = nil
entry_body = []
@content.each_line do |line|
case line
when /^\s*$/ then
next
when /^\w.*/ then
entries << [entry_name, entry_body] if entry_name
entry_name = $&
begin
time = parse_date entry_name
@time_cache[entry_name] = time
rescue ArgumentError
entry_name = nil
end
entry_body = []
when /^(\t| {8})?\*\s*(.*)/ then # "\t* file.c (func): ..."
entry_body << $2.dup
when /^(\t| {8})?\s*(\(.*)/ then # "\t(func): ..."
entry = $2
if entry_body.last =~ /:/ then
entry_body << entry.dup
else
continue_entry_body entry_body, entry
end
when /^(\t| {8})?\s*(.*)/ then
continue_entry_body entry_body, $2
end
end
entries << [entry_name, entry_body] if entry_name
entries.reject! do |(entry,_)|
entry == nil
end
entries
end
##
# Converts the ChangeLog into an RDoc::Markup::Document
def scan
@time_cache = {}
entries = parse_entries
grouped_entries = group_entries entries
doc = create_document grouped_entries
@top_level.comment = doc
@top_level
end
module Git
def parse_info(info)
/^\s*base-url\s*=\s*(.*\S)/ =~ info
@base_url = $1
end
def parse_entries
entries = []
@content.scan(/^commit\s+(\h{20})\h*\n((?:.+\n)*)\n((?: {4}.*\n+)*)/) do
entry_name, header, entry_body = $1, $2, $3.gsub(/^ {4}/, '')
# header = header.scan(/^ *(\S+?): +(.*)/).to_h
# date = header["CommitDate"] || header["Date"]
date = header[/^ *(?:Author)?Date: +(.*)/, 1]
author = header[/^ *Author: +(.*)/, 1]
begin
time = parse_date(header[/^ *CommitDate: +(.*)/, 1] || date)
@time_cache[entry_name] = time
author.sub!(/\s*<(.*)>/, '')
email = $1
entries << [entry_name, [author, email, date, entry_body]]
rescue ArgumentError
end
end
entries
end
def create_entries entries
# git log entries have no strictly itemized style like the old
# style, just assume Markdown.
entries.map do |commit, entry|
LogEntry.new(@base_url, commit, *entry)
end
end
LogEntry = Struct.new(:base, :commit, :author, :email, :date, :contents) do
HEADING_LEVEL = 3
def initialize(base, commit, author, email, date, contents)
case contents
when String
contents = RDoc::Markdown.parse(contents).parts.each do |body|
case body
when RDoc::Markup::Heading
body.level += HEADING_LEVEL + 1
end
end
case first = contents[0]
when RDoc::Markup::Paragraph
contents[0] = RDoc::Markup::Heading.new(HEADING_LEVEL + 1, first.text)
end
end
super
end
def level
HEADING_LEVEL
end
def aref
"label-#{commit}"
end
def label context = nil
aref
end
def text
case base
when nil
"#{date}"
when /%s/
"{#{date}}[#{base % commit}]"
else
"{#{date}}[#{base}#{commit}]"
end + " {#{author}}[mailto:#{email}]"
end
def accept visitor
visitor.accept_heading self
begin
if visitor.respond_to?(:code_object=)
code_object = visitor.code_object
visitor.code_object = self
end
contents.each do |body|
body.accept visitor
end
ensure
if visitor.respond_to?(:code_object)
visitor.code_object = code_object
end
end
end
def pretty_print q # :nodoc:
q.group(2, '[log_entry: ', ']') do
q.text commit
q.text ','
q.breakable
q.group(2, '[date: ', ']') { q.text date }
q.text ','
q.breakable
q.group(2, '[author: ', ']') { q.text author }
q.text ','
q.breakable
q.group(2, '[email: ', ']') { q.text email }
q.text ','
q.breakable
q.pp contents
end
end
end
end
end