Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update apidoc generation process #244

Merged
merged 3 commits into from Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 20 additions & 2 deletions .github/workflows/check.yml
Expand Up @@ -7,11 +7,29 @@ jobs:
name: documents updated
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.1
bundler-cache: true
- run: |
- uses: actions/checkout@v3
with:
fetch-depth: 0
path: puppeteer
repository: puppeteer/puppeteer
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Check puppeteer.api.json is updated
run: |
cd puppeteer
git checkout v$(cat ../development/DOCS_VERSION)
npm install && npm run build
cd ../
cp puppeteer/docs/puppeteer.api.json development/puppeteer.api.json
rm -rf puppeteer
git diff --exit-code
- name: Check api_coverage doc is updated
run: |
bundle exec ruby development/generate_api_coverage.rb
git diff --exit-code
1 change: 1 addition & 0 deletions development/DOCS_VERSION
@@ -0,0 +1 @@
15.3.2
150 changes: 53 additions & 97 deletions development/generate_api_coverage.rb
@@ -1,131 +1,85 @@
require 'bundler/setup'
require 'json'

# fetch raw api.md text from github.com/puppeteer/puppeteer
class RawApiMdReader
def initialize(git_tag)
@url = "https://raw.githubusercontent.com/puppeteer/puppeteer/#{git_tag}/docs/api.md"
class Member
def initialize(json)
@kind = json['kind']
@name = json['name']
@canonical_reference = json['canonicalReference']
@members = json['members']
end

# @returns [String]
def read
require 'net/http'
require 'uri'
attr_reader :kind, :name, :canonical_reference

uri = URI.parse(@url)
Net::HTTP.get_response(uri).tap(&:value).body
INSPECT_ALLOW_LIST = ['kind', 'canonicalReference', 'name']
def inspect
{
kind: @kind,
name: @name,
canonical_reference: @canonical_reference,
members: @members&.map { |member| member.select { |key, _| INSPECT_ALLOW_LIST.include?(key) } },
}.compact.inspect
end
end

class ApiMdParser
def initialize(raw_doc)
@raw = raw_doc.split("\n")
def class?
@kind == 'Class'
end

def parse
skip_until_class_docs
class_doc_chunks.map do |chunk|
ClassDocParser.new(chunk).parse
end
def method?
@kind == 'Method' || @kind == 'Function'
end

private def skip_until_class_docs
@raw.shift until @raw.first =~ /^### class:/
def property?
@kind == 'Variable' && @name =~ /^[a-z]/
end

private def class_doc_chunks
Enumerator.new do |docs|
loop do
buf = []
buf << @raw.shift
buf << @raw.shift until @raw.first =~ /^### /

docs << buf
break unless @raw.first.start_with?('### class:')
end
def members
@__members ||= @members.map do |json|
Member.new(json)
end
end
end

class ClassDoc
def initialize(name, methods, events)
@name = name
@methods = methods
@events = events
end
attr_reader :name, :methods, :events
end

class MethodDoc
def initialize(name)
@name = name
end
attr_reader :name
end

class EventDoc
def initialize(name)
@name = name
class ApiDocJsonParser
def initialize(raw_doc)
json = JSON.parse(raw_doc)
@root = Member.new(json)
end
attr_reader :name
end

class ClassDocParser
def initialize(md_lines)
@raw = md_lines
def puppeteer_doc
ClassDoc.new('Puppeteer', method_docs_for(puppeteer_entrypoint))
end

def parse
title = @raw.shift[11..-1]
skip_until_method_or_event_docs
methods = []
events = []
method_or_event_doc_chunks.each do |chunk|
if chunk.first.include?('event:')
events << EventDocParser.new(chunk).parse
elsif chunk.first.match(/#### [a-zA-Z]+\.([^(]+)/)
methods << MethodDocParser.new(chunk).parse
end
def class_docs
puppeteer_entrypoint.members.filter_map do |member|
ClassDoc.new(member.name, method_docs_for(member)) if member.class?
end

ClassDoc.new(title, methods, events)
end

private def skip_until_method_or_event_docs
@raw.shift until @raw.first.nil? || @raw.first =~ /^#### [a-zA-Z]/
private def puppeteer_entrypoint
@root.members.first
end

private def method_or_event_doc_chunks
Enumerator.new do |docs|
loop do
break if @raw.first.nil?
buf = []
buf << @raw.shift
buf << @raw.shift until @raw.first.nil? || @raw.first =~ /^#### /

docs << buf
end
private def method_docs_for(member)
member.members.filter_map do |m|
MethodDoc.new(m.name) if m.method? || m.property?
end
end
end

class MethodDocParser
def initialize(md_lines)
@raw = md_lines
end

def parse
MethodDoc.new(@raw.first.match(/#### [a-zA-Z]+\.([^(]+)/)[1])
class ClassDoc
def initialize(name, methods)
@name = name
@methods = methods
end
attr_reader :name, :methods
end

class EventDocParser
def initialize(md_lines)
@raw = md_lines
end

def parse
EventDoc.new(@raw.first[13...-1])
class MethodDoc
def initialize(name)
@name = name
end
attr_reader :name
end

require 'dry/inflector'
Expand Down Expand Up @@ -269,9 +223,11 @@ def api_coverages
end
end

raw_md = RawApiMdReader.new('v15.2.0').read
class_docs = ApiMdParser.new(raw_md).parse

apidoc_content = File.read(File.join(__dir__, 'puppeteer.api.json'))
parser = ApiDocJsonParser.new(apidoc_content)
class_docs = parser.class_docs
class_docs.delete_if { |doc| doc.name.start_with?('Puppeteer') }
class_docs.unshift(parser.puppeteer_doc)

File.open(File.join('.', 'docs', 'api_coverage.md'), 'w') do |f|
f.write("# API coverages\n")
Expand Down