mirror of https://github.com/freeCodeCamp/devdocs
parent
c14d91e966
commit
2f0ad7c09f
@ -0,0 +1,56 @@
|
|||||||
|
._threejs {
|
||||||
|
// Code blocks
|
||||||
|
pre, code {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0.2em 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 1em;
|
||||||
|
margin: 1em 0;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Links
|
||||||
|
a {
|
||||||
|
color: #049EF4;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Headings
|
||||||
|
h2 {
|
||||||
|
margin-top: 2em;
|
||||||
|
padding-bottom: 0.3em;
|
||||||
|
border-bottom: 1px solid #eaecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1em 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #dfe2e5;
|
||||||
|
padding: 6px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(2n) {
|
||||||
|
background-color: #f6f8fa;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,348 @@
|
|||||||
|
module Docs
|
||||||
|
class Threejs
|
||||||
|
class CleanHtmlFilter < Filter
|
||||||
|
def call
|
||||||
|
# Remove unnecessary elements
|
||||||
|
css('head, script, style').remove
|
||||||
|
|
||||||
|
# Add syntax highlighting CSS
|
||||||
|
style = doc.document.create_element('style')
|
||||||
|
style.content = <<-CSS
|
||||||
|
.highlight { background: #272b30; color: #e9ecef; border-radius: 4px; margin: 1em 0; }
|
||||||
|
.highlight pre { margin: 0; padding: 10px; }
|
||||||
|
.highlight .k { color: #cc7832; font-weight: bold; } /* Keyword */
|
||||||
|
.highlight .kd { color: #cc7832; font-weight: bold; } /* Keyword.Declaration */
|
||||||
|
.highlight .nb { color: #6897bb; } /* Name.Builtin */
|
||||||
|
.highlight .nx { color: #ffc66d; } /* Name.Other */
|
||||||
|
.highlight .nf { color: #ffc66d; } /* Name.Function */
|
||||||
|
.highlight .mi { color: #6897bb; } /* Literal.Number.Integer */
|
||||||
|
.highlight .s1 { color: #6a8759; } /* Literal.String.Single */
|
||||||
|
.highlight .s2 { color: #6a8759; } /* Literal.String.Double */
|
||||||
|
.highlight .c1 { color: #808080; font-style: italic; } /* Comment.Single */
|
||||||
|
.highlight .lineno { color: #606366; margin-right: 10px; -webkit-user-select: none; user-select: none; }
|
||||||
|
.highlight-javascript { padding: 0; }
|
||||||
|
|
||||||
|
/* Method signatures */
|
||||||
|
.sig { padding: 5px 10px; }
|
||||||
|
.sig-name { color: #ffc66d; }
|
||||||
|
.sig-param { color: #e9ecef; }
|
||||||
|
.sig-param .sig-type { color: #6897bb; }
|
||||||
|
.sig-returns { color: #cc7832; }
|
||||||
|
.sig-returns .sig-type { color: #6897bb; }
|
||||||
|
.sig-paren { color: #e9ecef; }
|
||||||
|
.property .pre { color: #cc7832; }
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
code.literal { background: #2b2b2b; padding: 2px 4px; border-radius: 3px; }
|
||||||
|
code.literal .pre { color: #e9ecef; }
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
.reference { color: #6897bb; text-decoration: none; }
|
||||||
|
.reference:hover { text-decoration: underline; }
|
||||||
|
.reference.external { color: #6a8759; }
|
||||||
|
|
||||||
|
/* Notes */
|
||||||
|
.admonition.note { background: #2b2b2b; padding: 12px 15px; border-left: 4px solid #6897bb; margin: 1em 0; }
|
||||||
|
.admonition-title { color: #6897bb; font-weight: bold; margin: 0 0 5px 0; }
|
||||||
|
CSS
|
||||||
|
doc.at_css('head') ? doc.at_css('head').add_child(style) : doc.add_child(style)
|
||||||
|
|
||||||
|
# Create a wrapper div for better styling
|
||||||
|
if root = at_css('body')
|
||||||
|
content = root.inner_html
|
||||||
|
else
|
||||||
|
content = doc.inner_html
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create Django-like structure
|
||||||
|
content = <<-HTML
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
#{content}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
doc.inner_html = content
|
||||||
|
|
||||||
|
# Handle source links
|
||||||
|
css('h2').each do |node|
|
||||||
|
if node.content.strip == 'Source'
|
||||||
|
content = node.next_element&.inner_html
|
||||||
|
if content
|
||||||
|
# Clean up any existing formatting
|
||||||
|
content = content.gsub(/<[^>]+>/, '')
|
||||||
|
# Extract the path from the content
|
||||||
|
if content =~ /src\/(.*?)\.js/
|
||||||
|
path = "/#{$1}.js"
|
||||||
|
formatted_link = %Q(<a class="reference external" href="https://github.com/mrdoob/three.js/blob/master/src#{path}">src#{path}</a>)
|
||||||
|
node.next_element.inner_html = formatted_link if node.next_element
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle method signatures
|
||||||
|
css('h3').each do |node|
|
||||||
|
content = node.inner_html
|
||||||
|
|
||||||
|
# Handle [method:this methodName]( param1, param2, ... ) format
|
||||||
|
content = content.gsub(/\[method:this\s+([^\]]+)\]\s*\((.*?)\)/) do |match|
|
||||||
|
method_name, params_str = $1, $2
|
||||||
|
|
||||||
|
# Format parameters
|
||||||
|
params = params_str.split(',').map do |param|
|
||||||
|
param = param.strip
|
||||||
|
if param.include?(' ')
|
||||||
|
type, name = param.split(' ', 2).map(&:strip)
|
||||||
|
"<span class='sig-param'><span class='sig-type'>#{type}</span> <span class='sig-name'>#{name}</span></span>"
|
||||||
|
else
|
||||||
|
"<span class='sig-param'>#{param}</span>"
|
||||||
|
end
|
||||||
|
end.join("<span class='sig-paren'>, </span>")
|
||||||
|
|
||||||
|
"<dt class='sig sig-object js' id='#{method_name}'>" \
|
||||||
|
"<span class='property'><span class='pre'>this</span></span>." \
|
||||||
|
"<span class='sig-name descname'>#{method_name}</span>" \
|
||||||
|
"<span class='sig-paren'>(</span>" \
|
||||||
|
"#{params}" \
|
||||||
|
"<span class='sig-paren'>)</span></dt>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle [method:returnType methodName]( param1, param2, ... ) format
|
||||||
|
content = content.gsub(/\[method:([^\s\]]+)\s+([^\]]+)\]\s*\((.*?)\)/) do |match|
|
||||||
|
return_type, method_name, params_str = $1, $2, $3
|
||||||
|
next if method_name.start_with?('this') # Skip if already handled above
|
||||||
|
|
||||||
|
# Format parameters
|
||||||
|
params = params_str.split(',').map do |param|
|
||||||
|
param = param.strip
|
||||||
|
if param.include?(' ')
|
||||||
|
type, name = param.split(' ', 2).map(&:strip)
|
||||||
|
"<span class='sig-param'><span class='sig-type'>#{type}</span> <span class='sig-name'>#{name}</span></span>"
|
||||||
|
else
|
||||||
|
"<span class='sig-param'>#{param}</span>"
|
||||||
|
end
|
||||||
|
end.join("<span class='sig-paren'>, </span>")
|
||||||
|
|
||||||
|
"<dt class='sig sig-object js' id='#{method_name}'>" \
|
||||||
|
"<span class='sig-name descname'>#{method_name}</span>" \
|
||||||
|
"<span class='sig-paren'>(</span>" \
|
||||||
|
"#{params}" \
|
||||||
|
"<span class='sig-paren'>)</span>" \
|
||||||
|
"<span class='sig-returns'><span class='sig-colon'>:</span> " \
|
||||||
|
"<span class='sig-type'>#{return_type}</span></span></dt>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle [method:returnType methodName] format (no parameters)
|
||||||
|
content = content.gsub(/\[method:([^\s\]]+)\s+([^\]]+)\](?!\()/) do |match|
|
||||||
|
return_type, method_name = $1, $2
|
||||||
|
"<dt class='sig sig-object js' id='#{method_name}'>" \
|
||||||
|
"<span class='sig-name descname'>#{method_name}</span>" \
|
||||||
|
"<span class='sig-paren'>(</span>" \
|
||||||
|
"<span class='sig-paren'>)</span>" \
|
||||||
|
"<span class='sig-returns'><span class='sig-colon'>:</span> " \
|
||||||
|
"<span class='sig-type'>#{return_type}</span></span></dt>"
|
||||||
|
end
|
||||||
|
|
||||||
|
node.inner_html = content
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle [name] placeholders in headers and constructor
|
||||||
|
css('h1, h3').each do |node|
|
||||||
|
content = node.inner_html
|
||||||
|
|
||||||
|
# Replace [name] with class name
|
||||||
|
content = content.gsub(/\[name\]/) do
|
||||||
|
name = slug.split('/').last.gsub('.html', '')
|
||||||
|
"<span class='descname'>#{name}</span>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format constructor parameters
|
||||||
|
content = content.gsub(/\[param:([^\]]+?)\s+([^\]]+?)\]/) do |match|
|
||||||
|
type, name = $1, $2
|
||||||
|
"<span class='sig-param'><span class='sig-type'>#{type}</span> <code class='sig-name'>#{name}</code></span>"
|
||||||
|
end
|
||||||
|
|
||||||
|
node.inner_html = content
|
||||||
|
end
|
||||||
|
|
||||||
|
# Clean up property formatting
|
||||||
|
css('h3').each do |node|
|
||||||
|
node.inner_html = node.inner_html.gsub(/\[property:([^\]]+?)\s+([^\]]+?)\]/) do |match|
|
||||||
|
type, name = $1, $2
|
||||||
|
"<dt class='sig sig-object js'>" \
|
||||||
|
"<span class='sig-name descname'>#{name}</span>" \
|
||||||
|
"<span class='sig-colon'>:</span> " \
|
||||||
|
"<span class='sig-type'>#{type}</span></dt>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Clean up external links
|
||||||
|
css('*').each do |node|
|
||||||
|
next if node.text?
|
||||||
|
|
||||||
|
# Handle example links [example:tag Title]
|
||||||
|
node.inner_html = node.inner_html.gsub(/\[example:([^\s\]]+)\s+([^\]]+)\]/) do |match|
|
||||||
|
tag, title = $1, $2
|
||||||
|
"<a class='reference external' href='https://threejs.org/examples/##{tag}'>#{title}</a>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle external links with [link:url text] format
|
||||||
|
node.inner_html = node.inner_html.gsub(/\[link:([^\s\]]+)\s+([^\]]+)\]/) do |match|
|
||||||
|
url, text = $1, $2
|
||||||
|
"<a class='reference external' href='#{url}'>#{text}</a>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle external links with [link:url] format
|
||||||
|
node.inner_html = node.inner_html.gsub(/\[link:([^\]]+)\]/) do |match|
|
||||||
|
url = $1
|
||||||
|
"<a class='reference external' href='#{url}'>#{url}</a>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle internal page links with text
|
||||||
|
node.inner_html = node.inner_html.gsub(/\[page:([^\]]+?)\s+([^\]]+?)\]/) do
|
||||||
|
path, text = $1, $2
|
||||||
|
"<a class='reference internal' href='#{path.downcase}'><code class='xref js js-#{path.downcase}'>#{text}</code></a>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle internal page links without text
|
||||||
|
node.inner_html = node.inner_html.gsub(/\[page:([^\]]+?)\]/) do |match|
|
||||||
|
path = $1
|
||||||
|
"<a class='reference internal' href='#{path.downcase}'><code class='xref js js-#{path.downcase}'>#{path}</code></a>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fix all href attributes to be lowercase and remove .html
|
||||||
|
css('a[href]').each do |link|
|
||||||
|
next if link['href'].start_with?('http')
|
||||||
|
link['href'] = link['href'].remove('../').downcase.sub(/\.html$/, '')
|
||||||
|
link['class'] = 'reference internal'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add section classes
|
||||||
|
css('h2').each do |node|
|
||||||
|
node['class'] = 'section-title'
|
||||||
|
section = node.next_element
|
||||||
|
if section
|
||||||
|
wrapper = doc.document.create_element('div')
|
||||||
|
wrapper['class'] = 'section'
|
||||||
|
node.after(wrapper)
|
||||||
|
wrapper.add_child(node)
|
||||||
|
current = section
|
||||||
|
while current && current.name != 'h2'
|
||||||
|
next_el = current.next
|
||||||
|
wrapper.add_child(current)
|
||||||
|
current = next_el
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format description paragraphs
|
||||||
|
css('p.desc').each do |node|
|
||||||
|
node['class'] = 'section-desc'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle inline code/backticks in text
|
||||||
|
css('p, li, dt, dd').each do |node|
|
||||||
|
next if node.at_css('pre') # Skip if contains a code block
|
||||||
|
|
||||||
|
# Replace backticks with proper code formatting
|
||||||
|
node.inner_html = node.inner_html.gsub(/`([^`]+)`/) do |match|
|
||||||
|
code = $1
|
||||||
|
"<code class='docutils literal notranslate'><span class='pre'>#{code}</span></code>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle inline code in property descriptions
|
||||||
|
css('.property-type').each do |node|
|
||||||
|
node.inner_html = node.inner_html.gsub(/`([^`]+)`/) do |match|
|
||||||
|
code = $1
|
||||||
|
"<code class='docutils literal notranslate'><span class='pre'>#{code}</span></code>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Clean up code blocks
|
||||||
|
css('pre').each do |node|
|
||||||
|
wrapper = doc.document.create_element('div')
|
||||||
|
wrapper['class'] = 'highlight'
|
||||||
|
node.replace(wrapper)
|
||||||
|
|
||||||
|
div = doc.document.create_element('div')
|
||||||
|
div['class'] = 'highlight-javascript notranslate'
|
||||||
|
wrapper.add_child(div)
|
||||||
|
|
||||||
|
pre = doc.document.create_element('pre')
|
||||||
|
pre['class'] = ''
|
||||||
|
div.add_child(pre)
|
||||||
|
|
||||||
|
# Format the code content
|
||||||
|
code = node.content.strip
|
||||||
|
|
||||||
|
# Add syntax highlighting spans
|
||||||
|
highlighted_code = highlight_javascript(code)
|
||||||
|
|
||||||
|
pre.inner_html = highlighted_code
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add proper heading IDs and classes
|
||||||
|
css('h1, h2, h3, h4').each do |node|
|
||||||
|
node['id'] ||= node.content.strip.downcase.gsub(/[^\w]+/, '-')
|
||||||
|
existing_class = node['class'].to_s
|
||||||
|
node['class'] = "#{existing_class} section-header"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove interactive examples
|
||||||
|
css('.threejs_example_container').remove
|
||||||
|
|
||||||
|
# Add note styling
|
||||||
|
css('p').each do |node|
|
||||||
|
if node.content.start_with?('Note:')
|
||||||
|
wrapper = doc.document.create_element('div')
|
||||||
|
wrapper['class'] = 'admonition note'
|
||||||
|
|
||||||
|
title = doc.document.create_element('p')
|
||||||
|
title['class'] = 'first admonition-title'
|
||||||
|
title.content = 'Note'
|
||||||
|
|
||||||
|
content = doc.document.create_element('p')
|
||||||
|
content['class'] = 'last'
|
||||||
|
content.inner_html = node.inner_html.sub('Note:', '').strip
|
||||||
|
|
||||||
|
wrapper.add_child(title)
|
||||||
|
wrapper.add_child(content)
|
||||||
|
node.replace(wrapper)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
doc
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def highlight_javascript(code)
|
||||||
|
code = code.gsub(/\b(function|return|var|let|const|if|else|for|while|do|switch|case|break|continue|new|try|catch|throw|this|typeof|instanceof|in|of|class|extends|super|import|export|default|null|undefined|true|false)\b/, '<span class="k">\1</span>') # keywords
|
||||||
|
code = code.gsub(/\b(\d+(\.\d+)?)\b/, '<span class="mi">\1</span>') # numbers
|
||||||
|
code = code.gsub(/'([^']*)'/, '<span class="s1">\'\1\'</span>') # single quotes
|
||||||
|
code = code.gsub(/"([^"]*)"/, '<span class="s2">"\1"</span>') # double quotes
|
||||||
|
code = code.gsub(/`([^`]*)`/, '<span class="s2">`\1`</span>') # template literals
|
||||||
|
code = code.gsub(/\/\/[^\n]*/, '<span class="c1">\0</span>') # single line comments
|
||||||
|
code = code.gsub(/\b(console|document|window|Array|Object|String|Number|Boolean|Function|Symbol|Map|Set|Promise|async|await)\b/, '<span class="nb">\1</span>') # built-ins
|
||||||
|
code = code.gsub(/([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/, '<span class="nx">\1</span>(') # function calls
|
||||||
|
code = code.gsub(/\b(addEventListener|querySelector|getElementById|setTimeout|setInterval)\b/, '<span class="nx">\1</span>') # common methods
|
||||||
|
|
||||||
|
# Add line numbers
|
||||||
|
lines = code.split("\n")
|
||||||
|
numbered_lines = lines.map.with_index(1) do |line, i|
|
||||||
|
"<span class=\"lineno\">#{i}</span>#{line}"
|
||||||
|
end
|
||||||
|
|
||||||
|
numbered_lines.join("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,54 @@
|
|||||||
|
module Docs
|
||||||
|
class Threejs
|
||||||
|
class EntriesFilter < Docs::EntriesFilter
|
||||||
|
def get_name
|
||||||
|
# Try to get name from the title first
|
||||||
|
if title = at_css('.lesson-title h1')&.content
|
||||||
|
title
|
||||||
|
else
|
||||||
|
# Fallback to path-based name for API docs
|
||||||
|
slug.split('/').last.gsub('.html', '').titleize
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_type
|
||||||
|
if slug.start_with?('api/en/')
|
||||||
|
# For API documentation, use the section as type
|
||||||
|
# e.g. "api/en/animation/AnimationAction" -> "Animation"
|
||||||
|
path_parts = slug.split('/')
|
||||||
|
if path_parts.length >= 3
|
||||||
|
path_parts[2].titleize
|
||||||
|
else
|
||||||
|
'API'
|
||||||
|
end
|
||||||
|
elsif slug.start_with?('manual/en/')
|
||||||
|
# For manual pages, get the section from the path
|
||||||
|
# e.g. "manual/en/introduction/Creating-a-scene" -> "Introduction"
|
||||||
|
path_parts = slug.split('/')
|
||||||
|
if path_parts.length >= 3
|
||||||
|
path_parts[2].titleize
|
||||||
|
else
|
||||||
|
'Manual'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
'Other'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def additional_entries
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
# Get all methods and properties from h3 headings
|
||||||
|
css('h3').each do |node|
|
||||||
|
name = node.content.strip
|
||||||
|
# Skip if it's a constructor or doesn't have an ID
|
||||||
|
next if name == get_name || !node['id']
|
||||||
|
|
||||||
|
entries << [name, node['id'], get_type]
|
||||||
|
end
|
||||||
|
|
||||||
|
entries
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,85 @@
|
|||||||
|
module Docs
|
||||||
|
class Threejs < FileScraper
|
||||||
|
self.name = 'Three.js'
|
||||||
|
self.type = 'threejs'
|
||||||
|
self.slug = 'threejs'
|
||||||
|
self.links = {
|
||||||
|
home: 'https://threejs.org/',
|
||||||
|
code: 'https://github.com/mrdoob/three.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
html_filters.push 'threejs/entries', 'threejs/clean_html'
|
||||||
|
|
||||||
|
# The content is directly in the body
|
||||||
|
options[:container] = 'body'
|
||||||
|
|
||||||
|
options[:skip] = %w(
|
||||||
|
prettify.js
|
||||||
|
lesson.js
|
||||||
|
lang.css
|
||||||
|
lesson.css
|
||||||
|
editor.html
|
||||||
|
list.js
|
||||||
|
page.js
|
||||||
|
)
|
||||||
|
|
||||||
|
options[:only_patterns] = [
|
||||||
|
/\Aapi\/en\/.+\.html/, # API documentation
|
||||||
|
/\Amanual\/en\/.+\.html/ # Manual pages
|
||||||
|
]
|
||||||
|
|
||||||
|
options[:skip_patterns] = [
|
||||||
|
/examples/,
|
||||||
|
/\A_/,
|
||||||
|
/\Aresources\//,
|
||||||
|
/\Ascenes\//
|
||||||
|
]
|
||||||
|
|
||||||
|
options[:attribution] = <<-HTML
|
||||||
|
© 2010–#{Time.current.year} Three.js Authors<br>
|
||||||
|
Licensed under the MIT License.
|
||||||
|
HTML
|
||||||
|
|
||||||
|
self.class_attribute :release
|
||||||
|
|
||||||
|
version '160' do
|
||||||
|
self.release = '160'
|
||||||
|
self.base_url = "https://threejs.org/docs"
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_latest_version(opts)
|
||||||
|
get_latest_github_release('mrdoob', 'three.js', opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initial_paths
|
||||||
|
paths = []
|
||||||
|
json_path = File.expand_path("docs/threejs~#{self.release}/list.json")
|
||||||
|
json_content = File.read(json_path)
|
||||||
|
json_data = JSON.parse(json_content)
|
||||||
|
|
||||||
|
# Process both API and manual sections
|
||||||
|
process_documentation(json_data['en'], paths)
|
||||||
|
paths
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_documentation(data, paths, prefix = '')
|
||||||
|
data.each do |category, items|
|
||||||
|
if items.is_a?(Hash)
|
||||||
|
if items.values.first.is_a?(String)
|
||||||
|
# This is a leaf node with actual pages
|
||||||
|
items.each do |name, path|
|
||||||
|
paths << "#{path}.html"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# This is a category with subcategories
|
||||||
|
items.each do |subcategory, subitems|
|
||||||
|
process_documentation(items, paths, "#{prefix}#{category}/")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in new issue