Skip to content

Commit

Permalink
Merge pull request #42 from razeware/development
Browse files Browse the repository at this point in the history
v1.0.7: 🐌 Varnish
  • Loading branch information
sammyd authored Sep 2, 2020
2 parents 4aa72b7 + affccbd commit 50740cd
Show file tree
Hide file tree
Showing 21 changed files with 675 additions and 114 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ gem 'cli-ui', '~> 1.3'
gem 'thor', '~> 1.0', '>= 1.0.1'

# Markdown processing
gem 'redcarpet', '~> 3.5'
gem 'commonmarker'

# HTTP Client
gem 'faraday'
Expand Down
13 changes: 8 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ GEM
benchmark (0.1.0)
cli-ui (1.3.0)
coderay (1.1.3)
commonmarker (0.21.0)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.6)
debase (0.2.4.1)
debase-ruby_core_source (>= 0.10.2)
Expand Down Expand Up @@ -115,24 +117,25 @@ GEM
rbnacl (7.1.1)
ffi
rchardet (1.8.0)
redcarpet (3.5.0)
regexp_parser (1.7.1)
reverse_markdown (2.0.0)
nokogiri
rexml (3.2.4)
rubocop (0.89.0)
rubocop (0.89.1)
parallel (~> 1.10)
parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.1.0, < 1.0)
rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.3.0)
parser (>= 2.7.1.4)
ruby-debug-ide (0.7.2)
rake (>= 0.8.1)
ruby-enum (0.8.0)
i18n
ruby-progressbar (1.10.1)
ruby2_keywords (0.0.2)
sassc (2.4.0)
Expand All @@ -147,7 +150,7 @@ GEM
rack-protection (= 2.0.8.1)
tilt (~> 2.0)
slack-notifier (2.3.2)
solargraph (0.39.13)
solargraph (0.39.15)
backport (~> 1.1)
benchmark
bundler (>= 1.17.2)
Expand Down Expand Up @@ -178,6 +181,7 @@ DEPENDENCIES
activesupport (~> 6.0)
aws-sdk-s3 (~> 1.64)
cli-ui (~> 1.3)
commonmarker
concurrent-ruby (~> 1.1)
debase (~> 0.2.4.1)
faraday
Expand All @@ -188,7 +192,6 @@ DEPENDENCIES
octokit!
rack-livereload
rbnacl
redcarpet (~> 3.5)
rubocop (~> 0.81)
ruby-debug-ide (~> 0.7.2)
sassc
Expand Down
1 change: 1 addition & 0 deletions app/commands/robles_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def self.exit_on_failure?
def render
book = runner.render(publish_file: options['publish_file'], local: options['local'])
p book.sections.first.chapters.last
p book.contributors.to_json
end

desc 'serve', 'starts local preview server'
Expand Down
39 changes: 11 additions & 28 deletions app/lib/image_provider/markdown_image_extractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,30 @@
module ImageProvider
# Takes a markdown file, and returns all the images URLs
class MarkdownImageExtractor
# Process markdown, and extract a list of images
class MarkdownRenderer < Redcarpet::Render::Base
attr_reader :images

def initialize
super
@images = []
end

def reset
@images = []
end

def image(link, _title, _alt_text)
images << link
nil
end
end

include Util::PathExtraction

def self.images_from(file)
new(file: file).images
end

def images
md_renderer.reset
renderer.render(markdown)
md_renderer.images.map { |path| { relative_path: cleanpath(path), absolute_path: cleanpath(apply_path(path)) } }
[].tap do |images|
doc.walk do |node|
images << image_record(node.url) if node.type == :image
end
end
end

def cleanpath(path)
Pathname.new(path).cleanpath.to_s
def image_record(url)
{ relative_path: cleanpath(url), absolute_path: cleanpath(apply_path(url)) }
end

def renderer
@renderer ||= Redcarpet::Markdown.new(md_renderer)
def cleanpath(path)
Pathname.new(path).cleanpath.to_s
end

def md_renderer
@md_renderer ||= MarkdownRenderer.new
def doc
@doc ||= CommonMarker.render_doc(markdown)
end

def markdown
Expand Down
1 change: 1 addition & 0 deletions app/lib/linting/file_existence_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Linting
module FileExistenceChecker
# This method shouldn't depend on the underlying filesystem
def file_exists?(path, case_insensitive: false)
path = path.to_s
directory_contents = Dir[Pathname.new(path).dirname + '*']
return directory_contents.include?(path) unless case_insensitive

Expand Down
12 changes: 12 additions & 0 deletions app/lib/linting/linter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ def lint_with_ui(options:, show_ui: true) # rubocop:disable Metrics/MethodLength
with_spinner(title: 'Validating image references', show: show_ui) do
annotations.concat(Linting::ImageLinter.new(book: book).lint)
end

if file_exists?(vend_file)
with_spinner(title: 'Validating {{bold:vend.yaml}}', show: show_ui) do
annotations.concat(Linting::VendLinter.new(file: vend_file).lint)
end
else
puts CLI::UI.fmt('{{x}} Unable to find {{bold:vend.yaml}}--skipping validation.')
end
end

def with_spinner(title:, show: true)
Expand Down Expand Up @@ -87,6 +95,10 @@ def check_publish_file_exists
false
end

def vend_file
Pathname.new(file).dirname + 'vend.yaml'
end

def book # rubocop:disable Metrics/MethodLength
@book ||= begin
parser = Parser::Publish.new(file: file)
Expand Down
5 changes: 3 additions & 2 deletions app/lib/linting/metadata/publish_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ module Linting
module Metadata
# Check for the required attributes in the publish.yaml file
class PublishAttributes
REQUIRED_ATTRIBUTES = %i[sku edition title description released_at authors segments materials_url
cover_image version_description difficulty platform language editor].freeze
REQUIRED_ATTRIBUTES = %i[sku edition title description_md released_at authors segments materials_url
cover_image version_description difficulty platform language editor
short_description].freeze

attr_reader :file, :attributes

Expand Down
132 changes: 132 additions & 0 deletions app/lib/linting/vend_linter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# frozen_string_literal: true

module Linting
# Lints vend.yaml
class VendLinter # rubocop:disable Metrics/ClassLength
VALID_PRICE_BANDS = %w(free 2020_full_book 2020_short_book 2020_deprecated_book).freeze
attr_reader :file, :vend_file

def initialize(file:)
@file = file
@annotations = []
end

def lint
load_file
return @annotations unless @annotations.empty?

check_price_band
check_total_percentage
return @annotations unless @annotations.empty?

check_for_razeware_user
@annotations
end

def check_price_band # rubocop:disable Metrics/MethodLength
if vend_file[:price_band].blank?
@annotations.push(
Annotation.new(
absolute_path: file,
annotation_level: 'warning',
start_line: 0,
end_line: 0,
title: 'Missing price_band attribute.',
message: 'The price_band attribute allows this book to be sold individually and should be included for all books.'
)
)
elsif !VALID_PRICE_BANDS.include?(vend_file[:price_band])
@annotations.push(
Annotation.new(
absolute_path: file,
annotation_level: 'failure',
start_line: 0,
end_line: 0,
title: 'Invalid price_band attribute.',
message: "price_band must be in (#{VALID_PRICE_BANDS.join(', ')})"
)
)
end
end

def check_total_percentage # rubocop:disable Metrics/MethodLength
if vend_file[:contributors].blank?
@annotations.push(
Annotation.new(
absolute_path: file,
annotation_level: 'warning',
start_line: 0,
end_line: 0,
title: 'Missing contributors attribute.',
message: 'The contributors attribute should be included for all books.'
)
)
return
end

total_contributor_percentage = vend_file[:contributors].sum(&:percentage)
return if total_contributor_percentage == 100

@annotations.push(
Annotation.new(
absolute_path: file,
annotation_level: 'failure',
start_line: 0,
end_line: 0,
message: "The sum of all contributor percentages should be 100. It is currently #{total_contributor_percentage}.",
title: 'Incorrect contribution sum.'
)
)
end

def check_for_razeware_user # rubocop:disable Metrics/MethodLength
return unless vend_file[:contributors].any? { |contributor| contributor.username == 'razeware' }

@annotations.push(
Annotation.new(
locate_razeware_username.merge(
absolute_path: file,
annotation_level: 'warning',
message: "The publisher's contribution should be attributed to the _razeware user, not the razeware user.",
title: 'Probable incorrect user.'
)
)
)
end

private

def load_file # rubocop:disable Metrics/MethodLength
@vend_file ||= begin
parser = Parser::Vend.new(file: file)
parser.parse
end
rescue Parser::Error => e
line_number = (e.message.match(/at line (\d+)/)&.captures&.first&.to_i || 0) + 1
@annotations.push(
Annotation.new(
absolute_path: e.file,
annotation_level: 'failure',
start_line: line_number,
end_line: line_number,
message: e.message,
title: 'Unable to parse contributors.'
)
)
end

def locate_razeware_username
IO.foreach(file).with_index do |line, line_number|
next unless line[/username:\s*razeware/]

start_column = line.index('razeware')
return {
start_line: line_number + 1,
end_line: line_number + 1,
start_column: start_column + 1,
end_column: start_column + 'razeware'.length + 1
}
end
end
end
end
17 changes: 16 additions & 1 deletion app/lib/parser/publish.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ module Parser
# Parses a publish.yaml file, and returns a Book model object
class Publish
include Util::PathExtraction
include Linting::FileExistenceChecker

VALID_BOOK_ATTRIBUTES = %i[sku edition title description released_at materials_url
cover_image gallery_image twitter_card_image trailer_video_url
version_description professional difficulty platform
language editor domains categories who_is_this_for_md
covered_concepts_md hide_chapter_numbers in_flux].freeze
covered_concepts_md hide_chapter_numbers in_flux forum_url
pages short_description recommended_skus].freeze

attr_reader :book

def parse
load_book_segments
load_vend_file
apply_additonal_metadata
update_authors_on_chapters
book
Expand All @@ -25,6 +28,10 @@ def load_book_segments
@book = Parser::BookSegments.new(file: segment_file).parse
end

def load_vend_file
book.assign_attributes(vend_file)
end

def apply_additonal_metadata
book.assign_attributes(additional_attributes)
book.root_path = root_directory
Expand All @@ -44,12 +51,20 @@ def publish_file
@publish_file ||= Psych.load_file(file).deep_symbolize_keys
end

def vend_file_path
Pathname.new(file).dirname + 'vend.yaml'
end

def authors
@authors = publish_file[:authors].map do |author|
Author.new(author)
end
end

def vend_file
@vend_file ||= file_exists?(vend_file_path) ? Parser::Vend.new(file: vend_file_path).parse : {}
end

def additional_attributes
@additional_attributes ||= publish_file.slice(*VALID_BOOK_ATTRIBUTES)
.assert_valid_keys(*VALID_BOOK_ATTRIBUTES)
Expand Down
Loading

0 comments on commit 50740cd

Please sign in to comment.