mirror of
https://github.com/System-End/highway.git
synced 2026-04-19 16:28:24 +00:00
Switch to markdown-backed project files
This commit is contained in:
parent
b04962bb04
commit
7f92bb49ad
11 changed files with 249 additions and 79 deletions
|
|
@ -1,4 +0,0 @@
|
|||
class MarkdownProjectsController < ApplicationController
|
||||
def index
|
||||
end
|
||||
end
|
||||
|
|
@ -1,49 +1,83 @@
|
|||
class ProjectsController < ApplicationController
|
||||
before_action :set_project, only: %i[ show edit update ]
|
||||
before_action :require_authentication, only: [:show, :edit, :update]
|
||||
|
||||
require 'yaml'
|
||||
require 'redcarpet'
|
||||
|
||||
def index
|
||||
@projects = Project.all
|
||||
end
|
||||
|
||||
def show
|
||||
@project = Project.find(params[:repo], params[:project_name])
|
||||
render_not_found unless @project
|
||||
end
|
||||
|
||||
def new
|
||||
@project = Project.new
|
||||
end
|
||||
|
||||
def create
|
||||
@project = Project.new(project_params)
|
||||
@project.user = current_user
|
||||
if @project.save
|
||||
redirect_to @project
|
||||
private
|
||||
|
||||
def load_projects
|
||||
projects = []
|
||||
Dir.glob(Rails.root.join('content/projects/*/*/journal.md')).each do |file|
|
||||
content = File.read(file)
|
||||
metadata, _ = parse_frontmatter(content)
|
||||
|
||||
# Extract repo and project name from path
|
||||
path_parts = file.split('/')
|
||||
repo = path_parts[-3]
|
||||
project_name = path_parts[-2]
|
||||
|
||||
projects << {
|
||||
repo: repo,
|
||||
project_name: project_name,
|
||||
title: metadata['title'],
|
||||
author: metadata['author'],
|
||||
description: metadata['description'],
|
||||
created_at: metadata['created_at']
|
||||
}
|
||||
end
|
||||
projects.sort_by { |p| p[:created_at] }.reverse
|
||||
end
|
||||
|
||||
def load_project(repo, project_name)
|
||||
file_path = Rails.root.join('content/projects', repo, project_name, 'journal.md')
|
||||
return nil unless File.exist?(file_path)
|
||||
|
||||
content = File.read(file_path)
|
||||
metadata, markdown_content = parse_frontmatter(content)
|
||||
|
||||
{
|
||||
repo: repo,
|
||||
project_name: project_name,
|
||||
title: metadata['title'],
|
||||
author: metadata['author'],
|
||||
description: metadata['description'],
|
||||
created_at: metadata['created_at'],
|
||||
content: render_markdown(markdown_content)
|
||||
}
|
||||
end
|
||||
|
||||
def parse_frontmatter(content)
|
||||
if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
||||
metadata = YAML.safe_load($1)
|
||||
content = content[$2.size..-1]
|
||||
[metadata, content]
|
||||
else
|
||||
render :new, status: :unprocessable_entity
|
||||
[{}, content]
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
def render_markdown(content)
|
||||
markdown = Redcarpet::Markdown.new(
|
||||
Redcarpet::Render::HTML,
|
||||
autolink: true,
|
||||
tables: true,
|
||||
fenced_code_blocks: true
|
||||
)
|
||||
markdown.render(content)
|
||||
end
|
||||
|
||||
def update
|
||||
if @project.update(project_params)
|
||||
redirect_to @project, notice: "Project was successfully updated."
|
||||
else
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
def render_not_found
|
||||
render file: "#{Rails.root}/public/404.html", status: :not_found
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_project
|
||||
@project = Project.find(params[:id])
|
||||
end
|
||||
|
||||
def project_params
|
||||
params.expect(project: [ :github_repo, :kitted_guide, :proposed_tier, :proposed_tier_explanation, :group_project, :name ])
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,14 +1,94 @@
|
|||
class Project < ApplicationRecord
|
||||
belongs_to :user
|
||||
has_many :posts, dependent: :destroy
|
||||
class Project
|
||||
attr_reader :repo, :project_name, :title, :author, :description, :created_at, :content
|
||||
|
||||
def initialize(attributes = {})
|
||||
@repo = attributes[:repo]
|
||||
@project_name = attributes[:project_name]
|
||||
@title = attributes[:title]
|
||||
@author = attributes[:author]
|
||||
@description = attributes[:description]
|
||||
@created_at = attributes[:created_at]
|
||||
@content = attributes[:content]
|
||||
end
|
||||
|
||||
def name
|
||||
title
|
||||
end
|
||||
|
||||
def github_slug
|
||||
return unless github_repo
|
||||
segments = github_repo.split("/")
|
||||
segments.last(2).join("/")
|
||||
"#{repo}/#{project_name}"
|
||||
end
|
||||
|
||||
def hours
|
||||
posts.sum(:hours)
|
||||
def github_repo
|
||||
"https://github.com/#{github_slug}"
|
||||
end
|
||||
|
||||
def created_at_date
|
||||
Date.parse(created_at)
|
||||
end
|
||||
|
||||
def formatted_created_at
|
||||
created_at_date.strftime("%B %d, %Y")
|
||||
end
|
||||
|
||||
def self.all
|
||||
Dir.glob(Rails.root.join('content/projects/*/*/journal.md')).map do |file|
|
||||
content = File.read(file)
|
||||
metadata, _ = parse_frontmatter(content)
|
||||
|
||||
# Extract repo and project name from path
|
||||
path_parts = file.split('/')
|
||||
repo = path_parts[-3]
|
||||
project_name = path_parts[-2]
|
||||
|
||||
new(
|
||||
repo: repo,
|
||||
project_name: project_name,
|
||||
title: metadata['title'],
|
||||
author: metadata['author'],
|
||||
description: metadata['description'],
|
||||
created_at: metadata['created_at']
|
||||
)
|
||||
end.sort_by(&:created_at_date).reverse
|
||||
end
|
||||
|
||||
def self.find(repo, project_name)
|
||||
file_path = Rails.root.join('content/projects', repo, project_name, 'journal.md')
|
||||
return nil unless File.exist?(file_path)
|
||||
|
||||
content = File.read(file_path)
|
||||
metadata, markdown_content = parse_frontmatter(content)
|
||||
|
||||
new(
|
||||
repo: repo,
|
||||
project_name: project_name,
|
||||
title: metadata['title'],
|
||||
author: metadata['author'],
|
||||
description: metadata['description'],
|
||||
created_at: metadata['created_at'],
|
||||
content: render_markdown(markdown_content)
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.parse_frontmatter(content)
|
||||
if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
||||
metadata = YAML.safe_load($1)
|
||||
content = content[$2.size..-1]
|
||||
[metadata, content]
|
||||
else
|
||||
[{}, content]
|
||||
end
|
||||
end
|
||||
|
||||
def self.render_markdown(content)
|
||||
markdown = Redcarpet::Markdown.new(
|
||||
Redcarpet::Render::HTML,
|
||||
autolink: true,
|
||||
tables: true,
|
||||
fenced_code_blocks: true
|
||||
)
|
||||
markdown.render(content)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
whi
|
||||
# Hello world
|
||||
|
||||
_by acorn_
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
<%# locals: (project:) %>
|
||||
<h1 class="text-2xl mb-4"><%= project.name %></h1>
|
||||
<%= link_to "View on GitHub", project.github_repo, class: "bg-[#96ABF9] text-white px-4 py-2 rounded hover:opacity-80 transition duration-200" %>
|
||||
<h1 class="text-2xl mb-4"><%= project.name %></h1>
|
||||
<%= link_to "View on GitHub", project.github_repo, class: "bg-[#96ABF9] text-white px-4 py-2 rounded hover:opacity-80 transition duration-200" %>
|
||||
|
||||
<% if project.user == current_user %>
|
||||
<div class="flex flex-wrap my-4 gap-4 items-center">
|
||||
<%= link_to "New Post", new_post_path(project: project), class: "bg-[#62D5C3] text-white px-4 py-2 rounded hover:opacity-80 transition duration-200" %>
|
||||
<div class="flex flex-wrap my-4 gap-4 items-center">
|
||||
<%= link_to "New Post", new_post_path(project: project), class: "bg-[#62D5C3] text-white px-4 py-2 rounded hover:opacity-80 transition duration-200" %>
|
||||
|
||||
<div class="opacity-70 hover:opacity-100 transition duration-100"><%= link_to "Edit", edit_project_path(project) %></div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,12 @@
|
|||
<p class="text-3xl font-bold">My projects:</p>
|
||||
|
||||
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-4 mt-4 sm:grid-cols-2 grid-cols-1">
|
||||
<%= link_to new_project_path, class: "bg-opacity-70 hover:bg-opacity-100 transition duration-100 bg-[#00D8C3] rounded-lg font-bold h-full justify-center text-center items-center p-4 text-xl flex flex-col leading-none" do %>
|
||||
<span>Create new project</span>
|
||||
<span class="text-6xl">+</span>
|
||||
<% end %>
|
||||
|
||||
<% @projects.each do |project| %>
|
||||
<%= link_to project_path(project), class: "block bg-[#2E2A54] max-w-4xl py-8 px-8 rounded-lg text-white hover:bg-[#3A3A6D] transition duration-100" do %>
|
||||
<%= link_to project_path(repo: project.repo, project_name: project.project_name), class: "block bg-[#2E2A54] max-w-4xl py-8 px-8 rounded-lg text-white hover:bg-[#3A3A6D] transition duration-100" do %>
|
||||
<h1 class="text-2xl"><%= project.name %> <span class="text-base text-[#96ABF9]">(<%= project.github_slug %>)</span></h1>
|
||||
<p class="mb-2">created by <span class="text-[#96ABF9]">[<%= "foo" %>]</span> </p>
|
||||
|
||||
<p class="opacity-70"><%= project.hours %> hours</p>
|
||||
<p class="mb-2">created by <span class="text-[#96ABF9]">[<%= project.author %>]</span></p>
|
||||
<p class="opacity-70"><%= project.description %></p>
|
||||
<p class="opacity-70 mt-2">Started on <%= project.formatted_created_at %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,19 +2,12 @@
|
|||
|
||||
<%= render partial: "header", locals: { project: @project } %>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<% @project.posts.each do |post| %>
|
||||
<%= link_to post_path(post), class: "block bg-[#2E2A54] max-w-4xl p-4 px-8 rounded-lg text-white hover:bg-[#3A3A6D] transition duration-100" do %>
|
||||
<p class="mb-2">posted by <span class="text-[#96ABF9]">[name]</span> <span class="opacity-50">// <%= time_ago_in_words(post.created_at) %> ago // <%= pluralize(post.hours, "hour") %> spent on </span> <span class="text-[#96ABF9]">[project]</span></p>
|
||||
<p class="text-xl font-bold mb-2"><%= post.name %></p>
|
||||
|
||||
<div class="opacity-70"><%= post.description %></div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<div class="prose prose-invert max-w-none mt-8">
|
||||
<%= @project.content.html_safe %>
|
||||
</div>
|
||||
|
||||
<% if current_user.admin? %>
|
||||
<details>
|
||||
<% if current_user&.admin? %>
|
||||
<details class="mt-8">
|
||||
<summary class="text-[#96ABF9] cursor-pointer">Project Details</summary>
|
||||
<%= (ap @project).html_safe %>
|
||||
</details>
|
||||
|
|
|
|||
|
|
@ -20,5 +20,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
<%= link_to "@#{current_user.username}", user_path(current_user), class: "#{current_page?(user_path(current_user)) || current_page?(edit_user_path(current_user)) ? 'bg-[#564CAD]' : 'hover:bg-[#564CAD]'} bg-[#2E2A54] p-2 transition duration-100 block" %>
|
||||
<% if current_user %>
|
||||
<%= link_to "@#{current_user.username}", user_path(current_user), class: "#{current_page?(user_path(current_user)) || current_page?(edit_user_path(current_user)) ? 'bg-[#564CAD]' : 'hover:bg-[#564CAD]'} bg-[#2E2A54] p-2 transition duration-100 block" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
@ -13,7 +13,8 @@ Rails.application.routes.draw do
|
|||
root "landing#index"
|
||||
resources :posts
|
||||
resources :users
|
||||
resources :projects
|
||||
get '/projects', to: 'projects#index'
|
||||
get '/projects/:repo/:project_name', to: 'projects#show', as: :project
|
||||
|
||||
get "/markdown", to: "markdown_projects#index"
|
||||
|
||||
|
|
@ -53,5 +54,4 @@ Rails.application.routes.draw do
|
|||
|
||||
get '/prize_box', to: 'users#prize_box', as: :prize_box
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
78
site/content/projects/hackclub/awesome-project/journal.md
Normal file
78
site/content/projects/hackclub/awesome-project/journal.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
title: "Highway - A Modern Web Development Framework"
|
||||
author: "Max Wofford"
|
||||
description: "A framework for building modern web applications with a focus on developer experience and performance"
|
||||
created_at: "2024-03-20"
|
||||
---
|
||||
|
||||
<!-- This is an AI generaated example file to test markdown rendering -->
|
||||
|
||||
# Highway - A Modern Web Development Framework
|
||||
|
||||
Highway is a framework designed to make web development more accessible and enjoyable. Built with modern best practices in mind, it provides a streamlined development experience while maintaining flexibility and power.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Modern Architecture**: Built on top of Rails 8, leveraging the latest web technologies
|
||||
- **Developer Experience**: Hot reloading, intuitive APIs, and comprehensive documentation
|
||||
- **Performance First**: Optimized for speed and efficiency out of the box
|
||||
- **Extensible**: Easy to customize and extend with plugins and middleware
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/hackclub/highway.git
|
||||
cd highway
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
bundle install
|
||||
```
|
||||
|
||||
3. Start the development server:
|
||||
```bash
|
||||
bin/dev
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
highway/
|
||||
├── app/
|
||||
│ ├── controllers/
|
||||
│ ├── models/
|
||||
│ └── views/
|
||||
├── config/
|
||||
├── content/
|
||||
│ └── projects/
|
||||
└── public/
|
||||
```
|
||||
|
||||
## Development Progress
|
||||
|
||||
### Week 1
|
||||
- Set up basic project structure
|
||||
- Implemented core routing system
|
||||
- Added basic authentication
|
||||
|
||||
### Week 2
|
||||
- Built project documentation system
|
||||
- Implemented markdown rendering
|
||||
- Added project submission workflow
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] Add more comprehensive testing
|
||||
- [ ] Improve documentation
|
||||
- [ ] Add more example projects
|
||||
- [ ] Implement CI/CD pipeline
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for more details.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
2
submissions.yml
Normal file
2
submissions.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
projects:
|
||||
- "https://github.com/Dongathan-Jong/SpotifyDisplay"
|
||||
Loading…
Add table
Reference in a new issue