-
Notifications
You must be signed in to change notification settings - Fork 3
wip: add live reload to site generator #103
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
Draft
phillmv
wants to merge
28
commits into
master
Choose a base branch
from
live-reload-mawl
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
6997c66
poking at a 'mawl server' mode for live reloading changes.
phillmv b5dc0d8
WIP: isolated some AdhocMarkdown import logic into EntryImporter to e…
phillmv aff262d
wip uh experimenting with loading stylesheet dynamically
phillmv c452cfa
silence sqlite warning, i get it
phillmv 15cdac0
don't rely on any secrets not in the codebase
phillmv b495acf
always run db:prepare?
phillmv 38de6b2
since we provide the SECRET_KEY we don't need this anymore
phillmv f3d3dd6
wip: let's avoid dynamic stylesheets for just now, when dynamically l…
phillmv feae41c
reintroduced concept of a template entry whose body is rendered as erb
phillmv 88b11ee
prepare db on mawl import and generate
phillmv a05b4c1
entry renderer now supplies default_url_options
phillmv 636a56d
AdHoc importer now also identifies erb files.
phillmv 2831c15
always link to archive with .html extension
phillmv 01f4a34
Swapped the active_storage routes prefix to be '_'
phillmv 7817e46
Added LinkRelativizer to EntryRenderer pipeline.
phillmv 46dd8d3
wip, separated mawl out from start-arquivo, fixed some settings
phillmv 04ea2dd
start-arquivo should load the current folder
phillmv 57dd488
Merge branch 'master' into tidy-up-mawl
phillmv 5783036
Merge branch 'master' into live-reload-mawl
phillmv 1c764fc
Merge branch 'tidy-up-mawl' into live-reload-mawl
phillmv 3d30600
added mawl console
phillmv 74d1ec3
wip: Hackily added the ability to live-reload stylesheets in static m…
phillmv 0d9f5fe
don't try to divine timestamps from c/mtime, which git does not set.
phillmv c08bcb9
Going to avoid this for now, think of a better solution down the road.
phillmv 8d5d20b
backed out file attachment experiment in non static controller
phillmv 23c2257
what if we fflag this for now?
phillmv 6911fe6
i did figure out a better way to handle templates: in the renderer!
phillmv d16750b
minor cleanup
phillmv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| class EntryImporter | ||
| attr_reader :current_notebook, :root_path | ||
| def initialize(current_notebook) | ||
| @current_notebook = current_notebook | ||
| @root_path = current_notebook.import_path | ||
| end | ||
|
|
||
| def resolve_and_import!(identifier) | ||
|
|
||
| # case identifier | ||
| # when "stylesheets/application" | ||
| # return render_stylesheet | ||
| # end | ||
| # TODO: replace hacky & brittle with more well-defined search | ||
| # i.e. exact lookups vs just fuzzy searching | ||
| # ALSO: need to think about how this would interact with scss templates. | ||
| file_path = build_file_path(identifier) | ||
| glob_path = file_path + "*" | ||
| file_path = Dir[glob_path].select { |f| f =~ /#{file_path}(\.html|\.md|\.markdown)+/ }.reject {|f| File.directory?(f) }.first | ||
| if file_path && looks_like_text?(file_path) | ||
| # TODO: hrm, should the identifier come from the request? this will blow up somehow | ||
| import!(identifier, file_path) | ||
| else | ||
| puts "couldn't find nothin' to import" | ||
| return nil | ||
| end | ||
| end | ||
|
|
||
| def import!(identifier, file_path) | ||
| entry_attributes = entry_attributes_from_markdown(identifier, file_path) | ||
|
|
||
| entry = add_entry!(entry_attributes) | ||
| end | ||
|
|
||
| def looks_like_text?(file_path) | ||
| file_path =~ /\.(md|markdown|html|erb)$/ | ||
| end | ||
|
|
||
| def build_file_path(path_info) | ||
| clean_path_info = Rack::Utils.clean_path_info(path_info) | ||
| ::File.join(@root_path, clean_path_info) | ||
| end | ||
|
|
||
| def entry_attributes_from_markdown(identifier, md_path) | ||
| loader = FrontMatterParser::Loader::Yaml.new(allowlist_classes: [Time, Date, DateTime]) | ||
| md_parser = FrontMatterParser::SyntaxParser::Md.new | ||
| parsed_file = FrontMatterParser::Parser.new(md_parser, loader: loader).call(File.read(md_path)) | ||
|
|
||
| occurred_at = parsed_file["occurred_at"] | ||
| if occurred_at.blank? | ||
| # let's try to guess it from the file | ||
| basename = File.basename(md_path) | ||
| date = basename.match(/([0-9]{4}-*[0-9]{2}-*[0-9]{2}-*)/).to_a[0] | ||
|
|
||
| # most of the time this does the right thing but it does have the habit | ||
| # of sometimes throwing an exception | ||
| begin | ||
| occurred_at = DateTime.parse(date.to_s) | ||
| rescue ArgumentError | ||
| end | ||
|
|
||
| # if still nil, let's look at the file itself | ||
| if occurred_at.nil? | ||
| # TODO: should throw an error maybe? Git does not set ctime. | ||
| occurred_at = File.ctime(md_path) | ||
| end | ||
| end | ||
|
|
||
| created_at = parsed_file["created_at"] || occurred_at | ||
| updated_at = parsed_file["updated_at"] || occurred_at | ||
|
|
||
| # if we're parsing front-mattered markdown, you don't get to define an | ||
| # identifier separate from the file's relative path, don't want to deal | ||
| # with collisions etc, too confusing, the ad hoc markdown is for ad hoc | ||
| # files, loosely slapped together! | ||
| # | ||
| # then, we lop off `.md`, `.markdown` and `html` from the suffix | ||
| entry_source = md_path # store the unmodified identifier as the "source" | ||
| identifier = identifier.gsub(/\.(md|markdown|html|erb)/, "") | ||
|
|
||
| # TODO: test this behaviour | ||
| if entry_source =~ /\.erb$/ | ||
| entry_kind = "template" | ||
| else | ||
| entry_kind = nil | ||
| end | ||
|
|
||
| entry_attributes = parsed_file.front_matter.merge({ | ||
| "identifier" => identifier, | ||
| "source" => entry_source, | ||
| "occurred_at" => occurred_at, | ||
| "body" => parsed_file.content, | ||
| "kind" => entry_kind, | ||
| "created_at" => created_at, | ||
| "updated_at" => updated_at, | ||
| skip_local_sync: true | ||
| }).slice(*Entry.accepted_attributes) | ||
|
|
||
| # handle metadata! | ||
| metadata_keys = (parsed_file.front_matter.keys - Entry.accepted_attributes) | ||
| if metadata_keys.any? | ||
| # if the user has specified a non Hash value, ie "metadata: foo", then | ||
| # throw a slightly easier to understand error here, instead of later on | ||
| # when we try to instantiate the Entry object & the error gets thrown there. | ||
| if entry_attributes["metadata"] && !entry_attributes["metadata"].is_a?(Hash) | ||
| raise "I expected the 'metadata' key on #{identifier} to be Hash, but something else is going on." | ||
| end | ||
|
|
||
| entry_attributes["metadata"] ||= {} | ||
| metadata_keys.each do |mkey| | ||
| entry_attributes["metadata"][mkey] ||= parsed_file.front_matter[mkey] | ||
| end | ||
| end | ||
|
|
||
| entry_attributes | ||
| end | ||
|
|
||
| def add_entry!(entry_attributes) | ||
| identifier = entry_attributes["identifier"] | ||
|
|
||
| # find or update the entry | ||
| entry = current_notebook.entries.find_by(identifier: identifier) | ||
|
|
||
| if entry | ||
| entry.update!(entry_attributes) | ||
| else | ||
| entry = current_notebook.entries.create(entry_attributes) | ||
| end | ||
|
|
||
| entry | ||
| end | ||
|
|
||
| def render_stylesheet | ||
| # okay lets do the dumbest thing possible | ||
| # reload the file everytime!!!! | ||
|
|
||
| scss_path = build_file_path("stylesheets/application.css.scss") | ||
|
|
||
| rendered_stylesheet = nil | ||
| if File.exist?(scss_path) | ||
| load_path = File.join(current_notebook.import_path, "stylesheets") | ||
|
|
||
| rendered_css = SassC::Engine.new(File.read(scss_path), { | ||
| filename: "application.css.scss", | ||
| syntax: :scss, | ||
| load_paths: [load_path], | ||
| }).render | ||
|
|
||
| # there can only be ONE application.css | ||
| if to_delete = current_notebook.entries.find_by(identifier: "stylesheets/application.css") | ||
| puts "Destroying extraneous stylesheets/application.css, so it can be replaced." | ||
| to_delete.destroy | ||
| end | ||
|
|
||
| rendered_stylesheet = current_notebook.entries.new | ||
| rendered_stylesheet.identifier = "stylesheets/application.css" | ||
| rendered_stylesheet.kind = :document | ||
| rendered_stylesheet.save! | ||
|
|
||
| blob = ActiveStorage::Blob.create_and_upload!(io: StringIO.new(rendered_css), | ||
| metadata: { analyzed: true }, | ||
| filename: "application.css") | ||
| # blob.analyze | ||
| rendered_stylesheet.files.create(blob_id: blob.id, created_at: blob.created_at) | ||
| end | ||
|
|
||
| rendered_stylesheet | ||
| end | ||
| end | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like, c'mon, isn't this nuts? this is a cute hack but if i give up on being able to parse random files in a random folder structure, it's obvious i should just define this in the frontmatter 🤔