# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'pygments' require 'zip' require 'nokogiri' require 'htmlentities' require_relative 'c_docs/doc_group.rb' module Pebble # Pebble C documentation processing class. class DocumentationC < Documentation MASTER_GROUP_IDS = %w(foundation graphics u_i smartstrap worker standard_c) def initialize(site, source, root, language='c') super(site) @site = site @url_root = root @source = source @tmp_dir = 'tmp/docs/c' @groups = [] @language = language run end private def language @language end def run cleanup download_and_extract(@source, @tmp_dir) hack_smartstraps process add_images end def cleanup FileUtils.rmtree @tmp_dir end def download_and_extract(zip, folder) open(zip) do | zf | Zip::File.open(zf.path) do | zipfile | zipfile.each do | entry | path = File.join(folder, entry.name).sub('/doxygen_sdk/', '/') FileUtils.mkdir_p(File.dirname(path)) zipfile.extract(entry, path) unless File.exist?(path) end end end end # This is a hack to get around a limitation with the documentation generator. # At present, it cannot handle the situation where a top level doc group exists on # Basalt but not Aplite. # Smartstraps is the only group that fits this pattern at the moment. # This hack copies the XML doc from the Basalt folder to the Aplite folder and removes # all of its contents. def hack_smartstraps basalt_xml = Nokogiri::XML(File.read("#{@tmp_dir}/basalt/xml/group___smartstrap.xml")) basalt_xml.search('.//memberdef').remove basalt_xml.search('.//innerclass').remove basalt_xml.search('.//sectiondef').remove File.open("#{@tmp_dir}/aplite/xml/group___smartstrap.xml", 'w') do |file| file.write(basalt_xml.to_xml) end end def process DocumentationC::MASTER_GROUP_IDS.each do |id| @groups << DocGroup.new(@url_root, @tmp_dir, 'aplite', id) end @groups.each { |group| group.load_xml('basalt') } mapping = [] @groups.each { |group| mapping += group.mapping_array } @groups.each do |group| group.process(mapping, 'aplite') group.process(mapping, 'basalt') end add_symbols(@groups) @groups.each { |group| @tree << group.to_branch } add_pages(@groups) add_redirects(mapping) end def add_images move_images('aplite') move_images('basalt') images = Dir.glob("#{@tmp_dir}/assets/images/**/*.png") images.each do |img| source = File.join(@site.source, '../tmp/docs/c/') if File.exists?(img) img.sub!('tmp/docs/c', '') @site.static_files << Jekyll::StaticFile.new(@site, source, '', img) end end end def move_images(platform) images = Dir.glob("#{@tmp_dir}/#{platform}/**/*.png") dir = File.join(@tmp_dir, 'assets', 'images', 'docs', 'c', platform) FileUtils.mkdir_p(dir) images.each do |img| FileUtils.cp(img, File.join(dir, File.basename(img))) end end # TODO: Make the groups handle their own subgroups and members etc # rubocop:disable Metrics/MethodLength, Metrics/AbcSize def add_symbols(groups) groups.each do |group| add_symbol(group.to_symbol) group.members.each do |member| add_symbol(member.to_symbol) member.children.each do |child| add_symbol(child.to_symbol) end end group.classes.each do |child| add_symbol(child.to_symbol) # OPINION: I don't think we want to have struct members as symbols. # struct.children.each do |child| # add_symbol(child.to_symbol) # end end add_symbols(group.groups) end end # rubocop:enable Metrics/MethodLength, Metrics/AbcSize def add_pages(groups) groups.each do |group| page = group.to_page(@site) page.set_language(@language) @pages << page add_pages(group.groups) end end def add_redirects(mapping) mapping.each do |map| next if map[:id].match(/_1/) @site.pages << Jekyll::RedirectPage.new(@site, @site.source, @url_root, map[:id] + '.html', map[:url]) end end end # Jekyll Page subclass for rendering the C documentation pages. class PageDocC < Jekyll::Page attr_reader :group def initialize(site, root, base, dir, group) @site = site @base = base @dir = root @name = dir @group = group process(@name) read_yaml(File.join(base, '_layouts', 'docs'), 'c.html') data['title'] = @group.name data['platforms'] = %w(aplite basalt) end def set_language(language) data['docs_language'] = language end def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID) super(attrs + %w(group)) end end end