├── .fixtures.yml ├── .github ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── jekyll-gh-pages.yml │ ├── mend.yml │ ├── nightly.yml │ ├── release.yml │ └── release_prep.yml ├── .gitignore ├── .rubocop.yml ├── .rubocop_todo.yml ├── .yardopts ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── Gemfile ├── JSON.md ├── LICENSE ├── README.md ├── Rakefile ├── lib ├── puppet-strings.rb ├── puppet-strings │ ├── describe.rb │ ├── json.rb │ ├── markdown.rb │ ├── markdown │ │ ├── base.rb │ │ ├── data_type.rb │ │ ├── defined_type.rb │ │ ├── function.rb │ │ ├── helpers.rb │ │ ├── puppet_class.rb │ │ ├── puppet_plan.rb │ │ ├── puppet_task.rb │ │ ├── resource_type.rb │ │ └── templates │ │ │ ├── classes_and_defines.erb │ │ │ ├── data_type.erb │ │ │ ├── data_type_function.erb │ │ │ ├── function.erb │ │ │ ├── puppet_task.erb │ │ │ ├── resource_type.erb │ │ │ └── table_of_contents.erb │ ├── monkey_patches │ │ └── display_object_command.rb │ ├── tasks.rb │ ├── tasks │ │ ├── generate.rb │ │ ├── gh_pages.rb │ │ └── validate.rb │ ├── version.rb │ ├── yard.rb │ └── yard │ │ ├── code_objects.rb │ │ ├── code_objects │ │ ├── base.rb │ │ ├── class.rb │ │ ├── data_type.rb │ │ ├── data_type_alias.rb │ │ ├── defined_type.rb │ │ ├── function.rb │ │ ├── group.rb │ │ ├── plan.rb │ │ ├── provider.rb │ │ ├── task.rb │ │ └── type.rb │ │ ├── handlers.rb │ │ ├── handlers │ │ ├── helpers.rb │ │ ├── json │ │ │ ├── base.rb │ │ │ └── task_handler.rb │ │ ├── puppet │ │ │ ├── base.rb │ │ │ ├── class_handler.rb │ │ │ ├── data_type_alias_handler.rb │ │ │ ├── defined_type_handler.rb │ │ │ ├── function_handler.rb │ │ │ └── plan_handler.rb │ │ └── ruby │ │ │ ├── base.rb │ │ │ ├── data_type_handler.rb │ │ │ ├── function_handler.rb │ │ │ ├── provider_handler.rb │ │ │ ├── rsapi_handler.rb │ │ │ ├── type_base.rb │ │ │ ├── type_extras_handler.rb │ │ │ └── type_handler.rb │ │ ├── parsers.rb │ │ ├── parsers │ │ ├── json │ │ │ ├── parser.rb │ │ │ └── task_statement.rb │ │ └── puppet │ │ │ ├── parser.rb │ │ │ └── statement.rb │ │ ├── tags.rb │ │ ├── tags │ │ ├── enum_tag.rb │ │ ├── factory.rb │ │ ├── overload_tag.rb │ │ ├── parameter_directive.rb │ │ ├── property_directive.rb │ │ └── summary_tag.rb │ │ ├── templates │ │ └── default │ │ │ ├── fulldoc │ │ │ └── html │ │ │ │ ├── css │ │ │ │ └── common.css │ │ │ │ ├── full_list_puppet_class.erb │ │ │ │ ├── full_list_puppet_data_type.erb │ │ │ │ ├── full_list_puppet_defined_type.erb │ │ │ │ ├── full_list_puppet_function.erb │ │ │ │ ├── full_list_puppet_plan.erb │ │ │ │ ├── full_list_puppet_provider.erb │ │ │ │ ├── full_list_puppet_task.erb │ │ │ │ ├── full_list_puppet_type.erb │ │ │ │ └── setup.rb │ │ │ ├── layout │ │ │ └── html │ │ │ │ ├── footer.erb │ │ │ │ ├── objects.erb │ │ │ │ └── setup.rb │ │ │ ├── puppet_class │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── header.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── source.erb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ ├── puppet_data_type │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── header.erb │ │ │ │ ├── method_details_list.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── source.erb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ ├── puppet_data_type_alias │ │ │ └── html │ │ │ │ ├── alias_of.erb │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── header.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── source.erb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ ├── puppet_defined_type │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── header.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── source.erb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ ├── puppet_function │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── header.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── source.erb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ ├── puppet_plan │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── header.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── source.erb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ ├── puppet_provider │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── collection.erb │ │ │ │ ├── features.erb │ │ │ │ ├── header.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── setup.rb │ │ │ │ └── summary.erb │ │ │ ├── puppet_task │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── header.erb │ │ │ │ ├── input.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── parameters.erb │ │ │ │ ├── setup.rb │ │ │ │ └── supports_noop.erb │ │ │ ├── puppet_type │ │ │ └── html │ │ │ │ ├── box_info.erb │ │ │ │ ├── deprecated.erb │ │ │ │ ├── features.erb │ │ │ │ ├── header.erb │ │ │ │ ├── note.erb │ │ │ │ ├── overview.erb │ │ │ │ ├── parameters.erb │ │ │ │ ├── setup.rb │ │ │ │ ├── summary.erb │ │ │ │ └── todo.erb │ │ │ └── tags │ │ │ ├── html │ │ │ ├── enum.erb │ │ │ └── puppet_overload.erb │ │ │ └── setup.rb │ │ └── util.rb └── puppet │ ├── application │ └── strings.rb │ ├── face │ └── strings.rb │ └── feature │ ├── rgen.rb │ └── yard.rb ├── puppet-strings.gemspec └── spec ├── acceptance ├── generate_json_spec.rb ├── generate_markdown_spec.rb └── running_strings_generate_spec.rb ├── fixtures ├── acceptance │ └── modules │ │ └── test │ │ ├── functions │ │ └── add.pp │ │ ├── lib │ │ └── puppet │ │ │ ├── datatypes │ │ │ └── acceptancedatatype.rb │ │ │ ├── functions │ │ │ └── 4x_function.rb │ │ │ ├── parser │ │ │ └── functions │ │ │ │ └── function3x.rb │ │ │ ├── provider │ │ │ └── server │ │ │ │ └── linux.rb │ │ │ └── type │ │ │ └── database.rb │ │ ├── manifests │ │ ├── init.pp │ │ └── triple_nested_classes.pp │ │ ├── metadata.json │ │ └── types │ │ └── elephant.pp ├── json │ └── backup.json ├── plans │ └── plan.pp ├── puppet │ ├── class.pp │ ├── function.pp │ └── type_alias.pp └── ruby │ ├── data_type.rb │ ├── func3x.rb │ ├── func4x.rb │ ├── func4x_1.rb │ ├── provider.rb │ ├── resource_api.rb │ └── resource_type.rb ├── markdownlint_style.rb ├── spec_helper.rb ├── spec_helper_acceptance.rb ├── spec_helper_acceptance_local.rb └── unit └── puppet-strings ├── describe_spec.rb ├── json_spec.rb ├── markdown └── base_spec.rb ├── markdown_spec.rb └── yard ├── code_objects └── task_spec.rb ├── handlers ├── json │ └── task_handler_spec.rb ├── puppet │ ├── class_handler_spec.rb │ ├── data_type_alias_handler_spec.rb │ ├── defined_type_handler_spec.rb │ └── function_handler_spec.rb └── ruby │ ├── data_type_handler_spec.rb │ ├── function_handler_spec.rb │ ├── provider_handler_spec.rb │ ├── rsapi_handler_spec.rb │ ├── type_extras_handler_spec.rb │ └── type_handler_spec.rb ├── parsers ├── json │ ├── parser_spec.rb │ └── task_statement_spec.rb └── puppet │ └── parser_spec.rb └── util_spec.rb /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | repositories: 3 | facts: 'https://github.com/puppetlabs/puppetlabs-facts.git' 4 | provision: 'https://github.com/puppetlabs/provision.git' 5 | puppet_agent: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' 6 | symlinks: 7 | test: "#{source_dir}/spec/fixtures/acceptance/modules/test" 8 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | Provide a detailed description of all the changes present in this pull request. 3 | 4 | ## Additional Context 5 | Add any additional context about the problem here. 6 | - [ ] Root cause and the steps to reproduce. (If applicable) 7 | - [ ] Thought process behind the implementation. 8 | 9 | ## Related Issues (if any) 10 | Mention any related issues or pull requests. 11 | 12 | ## Checklist 13 | - [ ] 🟢 Spec tests. 14 | - [ ] 🟢 Acceptance tests. 15 | - [ ] Manually verified. 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "ci" 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | pull_request: 8 | branches: 9 | - "main" 10 | workflow_dispatch: 11 | 12 | env: 13 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 14 | 15 | jobs: 16 | spec: 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | ruby_version: 21 | - "3.2" 22 | include: 23 | - ruby_version: '3.2' 24 | puppet_gem_version: '~> 8.0' 25 | runs_on: 26 | - "ubuntu-latest" 27 | - "windows-latest" 28 | name: "spec (${{ matrix.runs_on }} ruby ${{ matrix.ruby_version }} | puppet ${{matrix.puppet_gem_version}})" 29 | uses: "puppetlabs/cat-github-actions/.github/workflows/gem_ci.yml@main" 30 | secrets: "inherit" 31 | with: 32 | rake_task: "spec:coverage" 33 | ruby_version: ${{ matrix.ruby_version }} 34 | puppet_gem_version: ${{ matrix.puppet_gem_version }} 35 | runs_on: ${{ matrix.runs_on }} 36 | 37 | acceptance: 38 | needs: "spec" 39 | strategy: 40 | matrix: 41 | ruby_version: 42 | - "3.2" 43 | include: 44 | - ruby_version: '3.2' 45 | puppet_gem_version: 'https://github.com/puppetlabs/puppet' # puppet8' 46 | runs_on: 47 | - "ubuntu-latest" 48 | - "windows-latest" 49 | uses: "puppetlabs/cat-github-actions/.github/workflows/gem_acceptance.yml@main" 50 | secrets: "inherit" 51 | with: 52 | ruby_version: ${{ matrix.ruby_version }} 53 | puppet_version: ${{ matrix.puppet_gem_version }} 54 | runs_on: ${{ matrix.runs_on }} 55 | -------------------------------------------------------------------------------- /.github/workflows/jekyll-gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy GitHub Pages 2 | 3 | on: 4 | # Runs on pushes targeting the default branch 5 | push: 6 | branches: ["main"] 7 | 8 | # Allows you to run this workflow manually from the Actions tab 9 | workflow_dispatch: 10 | 11 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 12 | permissions: 13 | contents: read 14 | pages: write 15 | id-token: write 16 | 17 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 18 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 19 | concurrency: 20 | group: "pages" 21 | cancel-in-progress: false 22 | 23 | jobs: 24 | # Build job 25 | build: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v4 30 | - name: Setup Pages 31 | uses: actions/configure-pages@v5 32 | - name: Build with Jekyll 33 | uses: actions/jekyll-build-pages@v1 34 | with: 35 | source: ./ 36 | destination: ./_site 37 | - name: Upload artifact 38 | uses: actions/upload-pages-artifact@v3 39 | 40 | # Deployment job 41 | deploy: 42 | environment: 43 | name: github-pages 44 | url: ${{ steps.deployment.outputs.page_url }} 45 | runs-on: ubuntu-latest 46 | needs: build 47 | steps: 48 | - name: Deploy to GitHub Pages 49 | id: deployment 50 | uses: actions/deploy-pages@v4 51 | -------------------------------------------------------------------------------- /.github/workflows/mend.yml: -------------------------------------------------------------------------------- 1 | name: "mend" 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "main" 7 | schedule: 8 | - cron: "0 0 * * *" 9 | workflow_dispatch: 10 | 11 | jobs: 12 | 13 | mend: 14 | uses: "puppetlabs/cat-github-actions/.github/workflows/tooling_mend_ruby.yml@main" 15 | secrets: "inherit" 16 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: "nightly" 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | spec: 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | ruby_version: 14 | - "3.2" 15 | include: 16 | - ruby_version: '3.2' 17 | puppet_gem_version: '~> 8.0' 18 | runs_on: 19 | - "ubuntu-latest" 20 | - "windows-latest" 21 | name: "spec (${{ matrix.runs_on }} ruby ${{ matrix.ruby_version }} | puppet ${{matrix.puppet_gem_version}})" 22 | uses: "puppetlabs/cat-github-actions/.github/workflows/gem_ci.yml@main" 23 | secrets: "inherit" 24 | with: 25 | ruby_version: ${{ matrix.ruby_version }} 26 | puppet_gem_version: ${{ matrix.puppet_gem_version }} 27 | runs_on: ${{ matrix.runs_on }} 28 | 29 | acceptance: 30 | needs: "spec" 31 | strategy: 32 | matrix: 33 | ruby_version: 34 | - "3.2" 35 | include: 36 | - ruby_version: '3.2' 37 | puppet_gem_version: 'https://github.com/puppetlabs/puppet' # puppet8' 38 | runs_on: 39 | - "ubuntu-latest" 40 | - "windows-latest" 41 | uses: "puppetlabs/cat-github-actions/.github/workflows/gem_acceptance.yml@main" 42 | secrets: "inherit" 43 | with: 44 | ruby_version: ${{ matrix.ruby_version }} 45 | puppet_version: ${{ matrix.puppet_gem_version }} 46 | runs_on: ${{ matrix.runs_on }} 47 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Release" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | target: 7 | description: "The target for the release. This can be a commit sha or a branch." 8 | required: false 9 | default: "main" 10 | 11 | jobs: 12 | release: 13 | uses: "puppetlabs/cat-github-actions/.github/workflows/gem_release.yml@main" 14 | with: 15 | target: "${{ github.event.inputs.target }}" 16 | secrets: "inherit" 17 | -------------------------------------------------------------------------------- /.github/workflows/release_prep.yml: -------------------------------------------------------------------------------- 1 | name: "Release Prep" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | target: 7 | description: "The target for the release. This can be a commit sha or a branch." 8 | required: false 9 | default: "main" 10 | version: 11 | description: "Version of gem to be released." 12 | required: true 13 | 14 | jobs: 15 | release_prep: 16 | uses: "puppetlabs/cat-github-actions/.github/workflows/gem_release_prep.yml@main" 17 | with: 18 | target: "${{ github.event.inputs.target }}" 19 | version: "${{ github.event.inputs.version }}" 20 | secrets: "inherit" 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## MAC OS 2 | .DS_Store 3 | 4 | ## TEXTMATE 5 | *.tmproj 6 | tmtags 7 | 8 | ## EMACS 9 | *~ 10 | \#* 11 | .\#* 12 | 13 | ## VIM 14 | *.swp 15 | /tags 16 | 17 | ## BUNDLER 18 | .bundle 19 | Gemfile.local 20 | Gemfile.lock 21 | 22 | ## YARD 23 | .yardoc 24 | .yardwarns 25 | 26 | ## MODULE BUILDS 27 | **/pkg 28 | 29 | ## RubyMine 30 | /.idea/ 31 | 32 | ## rvm/rbenv 33 | /.ruby-version 34 | 35 | ## YARD output 36 | /doc/ 37 | 38 | ## Acceptance test artifacts 39 | /log/ 40 | /*.gem 41 | /spec/acceptance/nodesets/ 42 | /spec/fixtures/litmus_inventory.yaml 43 | /spec/fixtures/modules/ 44 | /spec/fixtures/manifests/ 45 | /inventory.yaml 46 | 47 | ## local coverage results 48 | /coverage/ 49 | 50 | ## local rspec config 51 | /.rspec-local 52 | 53 | ## local ruby environment 54 | /vendor/ 55 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | require: 4 | - rubocop-performance 5 | - rubocop-rspec 6 | 7 | AllCops: 8 | Exclude: 9 | - Gemfile 10 | - Rakefile 11 | - spec/fixtures/**/* 12 | - vendor/bundle/**/* 13 | NewCops: enable 14 | SuggestExtensions: false 15 | TargetRubyVersion: '3.1' 16 | 17 | # Disabled 18 | Layout/LineLength: 19 | Max: 200 20 | 21 | Lint/RedundantCopDisableDirective: 22 | Enabled: false 23 | 24 | Metrics/BlockLength: 25 | Enabled: false 26 | 27 | Style/ClassAndModuleChildren: 28 | Enabled: false 29 | 30 | Style/SpecialGlobalVars: 31 | Enabled: false 32 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --exclude lib/puppet-strings/yard/templates/ 2 | --no-private 3 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Setting ownership to the tooling team 2 | * @puppetlabs/devx @bastelfreak 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source ENV['GEM_SOURCE'] || "https://rubygems.org" 4 | 5 | gemspec 6 | 7 | def location_for(place_or_version, fake_version = nil) 8 | git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} 9 | file_url_regex = %r{\Afile:\/\/(?.*)} 10 | 11 | if place_or_version && (git_url = place_or_version.match(git_url_regex)) 12 | [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact 13 | elsif place_or_version && (file_url = place_or_version.match(file_url_regex)) 14 | ['>= 0', { path: File.expand_path(file_url[:path]), require: false }] 15 | else 16 | [place_or_version, { require: false }] 17 | end 18 | end 19 | 20 | group :development do 21 | gem 'puppet', *location_for(ENV['PUPPET_GEM_VERSION']) 22 | 23 | gem 'json_spec', '~> 1.1', '>= 1.1.5' 24 | 25 | gem 'mdl', '~> 0.11.0' 26 | 27 | gem 'pry', require: false 28 | gem 'pry-byebug', require: false 29 | gem 'pry-stack_explorer', require: false 30 | 31 | # Need the following otherwise we end up with puppetlabs_spec_helper 1.1.1 32 | gem 'mocha', '~> 1.0' 33 | gem 'puppetlabs_spec_helper' 34 | 35 | gem 'rake' 36 | gem 'rspec', '~> 3.1' 37 | gem 'rspec-its', '~> 1.0' 38 | 39 | gem 'rubocop', '~> 1.70.0', require: false 40 | gem 'rubocop-performance', '~> 1.16', require: false 41 | gem 'rubocop-rspec', '~> 3.0', require: false 42 | 43 | gem 'serverspec' 44 | gem 'simplecov', require: false 45 | gem 'simplecov-console', require: false 46 | 47 | gem 'redcarpet' 48 | end 49 | 50 | group :acceptance do 51 | gem 'puppet_litmus' 52 | gem 'net-ssh' 53 | end 54 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'puppet-lint/tasks/puppet-lint' 5 | require 'rspec/core/rake_task' 6 | require 'puppetlabs_spec_helper/tasks/fixtures' 7 | 8 | begin 9 | require 'puppet_litmus/rake_tasks' 10 | rescue LoadError 11 | # Gem not present 12 | end 13 | 14 | RSpec::Core::RakeTask.new(:spec) do |t| 15 | t.exclude_pattern = "spec/acceptance/**/*.rb" 16 | end 17 | 18 | namespace :spec do 19 | desc 'Run RSpec code examples with coverage collection' 20 | task :coverage do 21 | ENV['COVERAGE'] = 'yes' 22 | Rake::Task['spec'].execute 23 | end 24 | end 25 | 26 | 27 | RSpec::Core::RakeTask.new(:acceptance) do |t| 28 | t.pattern = "spec/unit/**/*.rb" 29 | end 30 | 31 | task :spec => :spec_clean 32 | task :acceptance => :spec_prep 33 | 34 | # Add our own tasks 35 | require 'puppet-strings/tasks' 36 | 37 | PuppetLint.configuration.send('disable_80chars') 38 | PuppetLint.configuration.ignore_paths = %w(acceptance/**/*.pp spec/**/*.pp pkg/**/*.pp) 39 | 40 | desc 'Validate Ruby source files and ERB templates.' 41 | task :validate do 42 | Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| 43 | sh "ruby -c #{ruby_file}" unless /spec\/fixtures/.match?(ruby_file) 44 | end 45 | Dir['lib/puppet-strings/yard/templates/**/*.erb'].each do |template| 46 | sh "erb -P -x -T '-' #{template} | ruby -c" 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/puppet-strings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # The root module for Puppet Strings. 4 | module PuppetStrings 5 | # The glob patterns used to search for files to document. 6 | DEFAULT_SEARCH_PATTERNS = ['manifests/**/*.pp', 'functions/**/*.pp', 'types/**/*.pp', 'lib/**/*.rb', 'tasks/*.json', 'plans/**/*.pp'].freeze 7 | 8 | # Generates documentation. 9 | # @param [Array] search_patterns The search patterns (e.g. manifests/**/*.pp) to look for files. 10 | # @param [Hash] options The options hash. 11 | # @option options [Boolean] :debug Enable YARD debug output. 12 | # @option options [Boolean] :backtrace Enable YARD backtraces. 13 | # @option options [String] :markup The YARD markup format to use (defaults to 'markdown'). 14 | # @option options [String] :path Write the selected format to a file path 15 | # @option options [Boolean] :markdown From the --format option, is the format Markdown? 16 | # @option options [Boolean] :json Is the format JSON? 17 | # @option options [Array] :yard_args The arguments to pass to yard. 18 | # @return [void] 19 | def self.generate(search_patterns = DEFAULT_SEARCH_PATTERNS, options = {}) 20 | require 'puppet-strings/yard' 21 | PuppetStrings::Yard.setup! 22 | 23 | # Format the arguments to YARD 24 | args = ['doc'] 25 | args << '--no-progress' 26 | args << '--debug' if options[:debug] 27 | args << '--backtrace' if options[:debug] 28 | args << "-m#{options[:markup] || 'markdown'}" 29 | 30 | file = nil 31 | if options[:json] || options[:markdown] 32 | file = if options[:json] 33 | options[:path] 34 | elsif options[:markdown] 35 | options[:path] || 'REFERENCE.md' 36 | end 37 | # Disable output and prevent stats/progress when writing to STDOUT 38 | args << '-n' 39 | args << '-q' unless file 40 | args << '--no-stats' unless file 41 | end 42 | 43 | yard_args = options[:yard_args] 44 | args += yard_args if yard_args 45 | args += search_patterns 46 | 47 | # Run YARD 48 | YARD::CLI::Yardoc.run(*args) 49 | 50 | # If outputting JSON, render the output 51 | render_json(file) if options[:json] && !options[:describe] 52 | 53 | # If outputting Markdown, render the output 54 | render_markdown(file) if options[:markdown] 55 | 56 | return unless options[:describe] 57 | 58 | render_describe(options[:describe_types], options[:describe_list], options[:providers], options[:list_providers]) 59 | end 60 | 61 | def self.puppet_5? 62 | Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') >= 0 63 | end 64 | 65 | def self.render_json(path) 66 | require 'puppet-strings/json' 67 | PuppetStrings::Json.render(path) 68 | end 69 | 70 | def self.render_markdown(path) 71 | require 'puppet-strings/markdown' 72 | PuppetStrings::Markdown.render(path) 73 | end 74 | 75 | def self.render_describe(describe_types, list = false, show_providers = true, list_providers = false) 76 | require 'puppet-strings/describe' 77 | PuppetStrings::Describe.render(describe_types, list, show_providers, list_providers) 78 | end 79 | 80 | # Runs the YARD documentation server. 81 | # @param [Array] args The arguments to YARD. 82 | def self.run_server(*args) 83 | require 'puppet-strings/yard' 84 | PuppetStrings::Yard.setup! 85 | 86 | YARD::CLI::Server.run(*args) 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/puppet-strings/describe.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | require 'puppet-strings/json' 5 | 6 | # The module for command line documentation related functionality. 7 | module PuppetStrings::Describe 8 | # Renders requested types or a summarized list in the current YARD registry to STDOUT. 9 | # @param [Array] describe_types The list of names of the types to be displayed. 10 | # @param [bool] list_types Create the summarized list instead of describing each type. 11 | # @param [bool] show_type_providers Show details of the providers of a specified type. 12 | # @param [bool] list_providers Create a summarized list of providers. 13 | # @return [void] 14 | def self.render(describe_types = [], list_types = false, show_type_providers = true, list_providers = false) 15 | document = { 16 | defined_types: YARD::Registry.all(:puppet_defined_type).sort_by!(&:name).map!(&:to_hash), 17 | resource_types: YARD::Registry.all(:puppet_type).sort_by!(&:name).map!(&:to_hash), 18 | providers: YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash) 19 | } 20 | # if --list flag passed, produce a summarized list of types 21 | if list_types 22 | puts 'These are the types known to puppet:' 23 | document[:resource_types].each { |t| list_one(t) } 24 | 25 | # if a type(s) has been passed, show the details of that type(s) 26 | elsif describe_types 27 | type_names = {} 28 | describe_types.each { |name| type_names[name] = true } 29 | 30 | document[:resource_types].each do |t| 31 | show_one_type(t, show_type_providers) if type_names[t[:name].to_s] 32 | end 33 | 34 | # if --providers flag passed, produce a summarized list of providers 35 | elsif list_providers 36 | puts 'These are the providers known to puppet:' 37 | document[:providers].each { |t| list_one(t) } 38 | end 39 | end 40 | 41 | def self.show_one_type(resource_type, providers = true) 42 | puts format("\n%s\n%s", name: resource_type[:name], underscore: '=' * resource_type[:name].length) 43 | puts resource_type[:docstring][:text] 44 | 45 | combined_list = (resource_type[:parameters].nil? ? [] : resource_type[:parameters]) + 46 | (resource_type[:properties].nil? ? [] : resource_type[:properties]) 47 | 48 | return unless combined_list.any? 49 | 50 | puts "\nParameters\n----------" 51 | combined_list.sort_by { |p| p[:name] }.each { |p| show_one_parameter(p) } 52 | return unless providers 53 | 54 | puts "\nProviders\n---------" 55 | resource_type[:providers]&.sort_by { |p| p[:name] }&.each { |p| puts p[:name].to_s.ljust(15) } 56 | end 57 | 58 | def self.show_one_parameter(parameter) 59 | puts format("\n- **%s**\n", name: parameter[:name]) 60 | puts parameter[:description] 61 | puts format('Valid values are `%s`.', values: parameter[:values].join('`, `')) unless parameter[:values].nil? 62 | puts format('Requires features %s.', required_features: parameter[:required_features]) unless parameter[:required_features].nil? 63 | end 64 | 65 | def self.list_one(object) 66 | targetlength = 48 67 | shortento = targetlength - 4 68 | contentstring = object[:docstring][:text] 69 | end_of_line = contentstring.index("\n") # "." gives closer results to old describeb, but breaks for '.k5login' 70 | contentstring = contentstring[0..end_of_line] unless end_of_line.nil? 71 | contentstring = "#{contentstring[0..shortento]} ..." if contentstring.length > targetlength 72 | 73 | puts "#{object[:name].to_s.ljust(15)} - #{contentstring}" 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/puppet-strings/json.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'json' 4 | 5 | # The module for JSON related functionality. 6 | module PuppetStrings::Json 7 | # Renders the current YARD registry as JSON to the given file (or STDOUT if nil). 8 | # @param [String] file The path to the output file to render the registry to. If nil, output will be to STDOUT. 9 | # @return [void] 10 | def self.render(file = nil) 11 | document = { 12 | puppet_classes: YARD::Registry.all(:puppet_class).sort_by!(&:name).map!(&:to_hash), 13 | data_types: YARD::Registry.all(:puppet_data_type).sort_by!(&:name).map!(&:to_hash), 14 | data_type_aliases: YARD::Registry.all(:puppet_data_type_alias).sort_by!(&:name).map!(&:to_hash), 15 | defined_types: YARD::Registry.all(:puppet_defined_type).sort_by!(&:name).map!(&:to_hash), 16 | resource_types: YARD::Registry.all(:puppet_type).sort_by!(&:name).map!(&:to_hash), 17 | providers: YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash), 18 | puppet_functions: YARD::Registry.all(:puppet_function).sort_by!(&:name).map!(&:to_hash), 19 | puppet_tasks: YARD::Registry.all(:puppet_task).sort_by!(&:name).map!(&:to_hash), 20 | puppet_plans: YARD::Registry.all(:puppet_plan).sort_by!(&:name).map!(&:to_hash) 21 | # TODO: Need Ruby documentation? 22 | } 23 | 24 | if file 25 | File.open(file, 'w') do |f| 26 | f.write(JSON.pretty_generate(document)) 27 | f.write("\n") 28 | end 29 | else 30 | puts JSON.pretty_generate(document) 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/json' 4 | 5 | # module for parsing Yard Registries and generating markdown 6 | module PuppetStrings::Markdown 7 | require_relative 'markdown/puppet_class' 8 | require_relative 'markdown/function' 9 | require_relative 'markdown/defined_type' 10 | require_relative 'markdown/data_type' 11 | require_relative 'markdown/resource_type' 12 | require_relative 'markdown/puppet_task' 13 | require_relative 'markdown/puppet_plan' 14 | 15 | # Get classes that handle collecting and rendering each section/group. 16 | # 17 | # @return [Array[class]] The classes 18 | def self.groups 19 | [ 20 | PuppetStrings::Markdown::PuppetClass, 21 | PuppetStrings::Markdown::DefinedType, 22 | PuppetStrings::Markdown::ResourceType, 23 | PuppetStrings::Markdown::Function, 24 | PuppetStrings::Markdown::DataType, 25 | PuppetStrings::Markdown::PuppetTask, 26 | PuppetStrings::Markdown::PuppetPlan 27 | ] 28 | end 29 | 30 | # generates markdown documentation 31 | # @return [String] markdown doc 32 | def self.generate 33 | output = [ 34 | "# Reference\n\n", 35 | "\n\n", 36 | "## Table of Contents\n\n" 37 | ] 38 | 39 | # Create table of contents 40 | template = erb(File.join(__dir__, 'markdown', 'templates', 'table_of_contents.erb')) 41 | groups.each do |group| 42 | group_name = group.group_name 43 | items = group.items.map(&:toc_info) 44 | has_private = items.any? { |item| item[:private] } 45 | has_public = items.any? { |item| !item[:private] } 46 | 47 | output << template.result(binding) 48 | end 49 | 50 | # Create actual contents 51 | groups.each do |group| 52 | items = group.items.reject(&:private?) 53 | unless items.empty? 54 | output << "## #{group.group_name}\n\n" 55 | output.append(items.map(&:render)) 56 | end 57 | end 58 | 59 | output.join 60 | end 61 | 62 | # mimicks the behavior of the json render, although path will never be nil 63 | # @param [String] path path to destination file 64 | def self.render(path = nil) 65 | if path.nil? 66 | puts generate 67 | exit 68 | else 69 | File.write(path, generate) 70 | YARD::Logger.instance.debug "Wrote markdown to #{path}" 71 | end 72 | end 73 | 74 | # Helper function to load an ERB template. 75 | # 76 | # @param [String] path The full path to the template file. 77 | # @return [ERB] Template 78 | def self.erb(path) 79 | ERB.new(File.read(path), trim_mode: '-') 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/data_type.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # This class encapsualtes ruby data types and puppet type aliases 7 | class DataType < Base 8 | attr_reader :alias_of, :functions 9 | 10 | group_name 'Data types' 11 | yard_types %i[puppet_data_type puppet_data_type_alias] 12 | 13 | def initialize(registry) 14 | @template = 'data_type.erb' 15 | super(registry, 'data type') 16 | @alias_of = registry[:alias_of] unless registry[:alias_of].nil? 17 | @functions = @registry[:functions]&.map { |func| DataType::Function.new(func) } 18 | end 19 | 20 | def render 21 | super(@template) 22 | end 23 | end 24 | 25 | # Generates Markdown for a Puppet Function. 26 | class DataType::Function < Base 27 | def initialize(registry) 28 | super(registry, 'data_type_function') 29 | end 30 | 31 | def render 32 | super('data_type_function.erb') 33 | end 34 | 35 | def signature 36 | @registry[:signature] 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/defined_type.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # Generates Markdown for a Puppet Defined Type. 7 | class DefinedType < Base 8 | group_name 'Defined types' 9 | yard_types [:puppet_defined_type] 10 | 11 | def initialize(registry) 12 | @template = 'classes_and_defines.erb' 13 | super(registry, 'defined type') 14 | end 15 | 16 | def render 17 | super(@template) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/function.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # Generates Markdown for a Puppet Function. 7 | class Function < Base 8 | attr_reader :signatures 9 | 10 | group_name 'Functions' 11 | yard_types [:puppet_function] 12 | 13 | def initialize(registry) 14 | @template = 'function.erb' 15 | super(registry, 'function') 16 | @signatures = [] 17 | registry[:signatures].each do |sig| 18 | @signatures.push(Signature.new(sig)) 19 | end 20 | end 21 | 22 | def render 23 | super(@template) 24 | end 25 | 26 | def type 27 | t = @registry[:type] 28 | if t.include?('ruby4x') 29 | 'Ruby 4.x API' 30 | elsif t.include?('ruby3') 31 | 'Ruby 3.x API' 32 | elsif t.include?('ruby') 33 | 'Ruby' 34 | else 35 | 'Puppet Language' 36 | end 37 | end 38 | 39 | def error_type(type) 40 | "`#{type.split[0]}`" 41 | end 42 | 43 | def error_text(text) 44 | text.split.drop(1).join(' ').to_s 45 | end 46 | end 47 | 48 | # Implements methods to retrieve information about a function signature. 49 | class Function::Signature < Base 50 | def initialize(registry) 51 | @registry = registry 52 | super(@registry, 'function signature') 53 | end 54 | 55 | def signature 56 | @registry[:signature] 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Helpers for rendering Markdown 4 | module PuppetStrings::Markdown::Helpers 5 | # Formats code as either inline or a block. 6 | # 7 | # Note that this does not do any escaping even if the code contains ` or ```. 8 | # 9 | # @param [String] code The code to format. 10 | # @param [Symbol] type The type of the code, e.g. :text, :puppet, or :ruby. 11 | # @param [String] block_prefix String to insert before if it’s a block. 12 | # @param [String] inline_prefix String to insert before if it’s inline. 13 | # @returns [String] Markdown 14 | def code_maybe_block(code, type: :puppet, block_prefix: "\n\n", inline_prefix: ' ') 15 | if code.to_s.include?("\n") 16 | "#{block_prefix}```#{type}\n#{code}\n```" 17 | else 18 | "#{inline_prefix}`#{code}`" 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/puppet_class.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # Generates Markdown for a Puppet Class. 7 | class PuppetClass < Base 8 | group_name 'Classes' 9 | yard_types [:puppet_class] 10 | 11 | def initialize(registry) 12 | @template = 'classes_and_defines.erb' 13 | super(registry, 'class') 14 | end 15 | 16 | def render 17 | super(@template) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/puppet_plan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # Generates Markdown for a Puppet Plan. 7 | class PuppetPlan < Base 8 | group_name 'Plans' 9 | yard_types [:puppet_plan] 10 | 11 | def initialize(registry) 12 | @template = 'classes_and_defines.erb' 13 | super(registry, 'plan') 14 | end 15 | 16 | def render 17 | super(@template) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/puppet_task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # Generates Markdown for a Puppet Task. 7 | class PuppetTask < Base 8 | group_name 'Tasks' 9 | yard_types [:puppet_task] 10 | 11 | def initialize(registry) 12 | @template = 'puppet_task.erb' 13 | @registry = registry 14 | super(registry, 'task') 15 | end 16 | 17 | def render 18 | super(@template) 19 | end 20 | 21 | def supports_noop 22 | @registry[:supports_noop] 23 | end 24 | 25 | def input_method 26 | @registry[:input_method] 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/resource_type.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/markdown/base' 4 | 5 | module PuppetStrings::Markdown 6 | # Generates Markdown for a Puppet Resource Type. 7 | class ResourceType < Base 8 | group_name 'Resource types' 9 | yard_types [:puppet_type] 10 | 11 | def initialize(registry) 12 | @template = 'resource_type.erb' 13 | super(registry, 'type') 14 | end 15 | 16 | def render 17 | super(@template) 18 | end 19 | 20 | def properties 21 | return nil unless @registry[:properties] 22 | 23 | @registry[:properties].sort_by { |p| p[:name] } 24 | end 25 | 26 | def checks 27 | return nil unless @registry[:checks] 28 | 29 | @registry[:checks].sort_by { |p| p[:name] } 30 | end 31 | 32 | # "checks" (such as "onlyif" or "creates") are another type of property 33 | def properties_and_checks 34 | return nil if properties.nil? && checks.nil? 35 | 36 | ((properties || []) + (checks || [])).sort_by { |p| p[:name] }.map do |prop| 37 | prop[:link] = clean_link("$#{name}::#{prop[:name]}") 38 | prop 39 | end 40 | end 41 | 42 | def parameters 43 | return nil unless @registry[:parameters] 44 | 45 | @registry[:parameters].sort_by { |p| p[:name] }.map do |param| 46 | param[:link] = clean_link("$#{name}::#{param[:name]}") 47 | param 48 | end 49 | end 50 | 51 | def regex_in_data_type?(data_type) 52 | m = data_type.match(%r{\w+\[/.*/\]}) 53 | m unless m.nil? || m.to_a.empty? 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/classes_and_defines.erb: -------------------------------------------------------------------------------- 1 | ### `<%= name %>` 2 | 3 | <% if text -%> 4 | <%= text %> 5 | <% elsif summary -%> 6 | <%= summary %> 7 | <% else -%> 8 | <%= "The #{name} class." %> 9 | <% end -%> 10 | 11 | <% if deprecated -%> 12 | * **DEPRECATED** <%= deprecated %> 13 | 14 | <% end -%> 15 | <% if todo -%> 16 | * **TODO** <%= todo %> 17 | 18 | <% end -%> 19 | <% if note -%> 20 | * **Note** <%= note %> 21 | 22 | <% end -%> 23 | <% if since -%> 24 | * **Since** <%= since %> 25 | 26 | <% end -%> 27 | <% if see -%> 28 | * **See also** 29 | <% see.each do |sa| -%> 30 | <% if sa[:name] -%> 31 | <%= " * #{sa[:name]}" %> 32 | <% end -%> 33 | <% if sa[:text] -%> 34 | <%= " * #{sa[:text]}" %> 35 | <% end -%> 36 | <% end -%> 37 | 38 | <% end -%> 39 | <% if examples -%> 40 | #### Examples 41 | 42 | <% examples.each do |eg| -%> 43 | ##### <%= eg[:name] %> 44 | 45 | ```puppet 46 | <%= eg[:text] %> 47 | ``` 48 | 49 | <% end -%> 50 | <% end -%> 51 | <% if params -%> 52 | #### Parameters 53 | 54 | The following parameters are available in the `<%= name %>` <%= @type %>: 55 | 56 | <% params.each do |param| -%> 57 | * [`<%= param[:name] %>`](#<%= param[:link] %>) 58 | <% end -%> 59 | 60 | <% params.each do |param| -%> 61 | ##### `<%= param[:name] %>` 62 | 63 | <% if param[:types] -%> 64 | Data type:<%= code_maybe_block(param[:types].join(', ')) %> 65 | 66 | <% end -%> 67 | <%= param[:text] %> 68 | 69 | <% if options_for_param(param[:name]) -%> 70 | Options: 71 | 72 | <% options_for_param(param[:name]).each do |o| -%> 73 | <% if o[:opt_types] -%> 74 | * **<%= o[:opt_name] %>** `<%= o[:opt_types][0] %>`: <%= o[:opt_text] %> 75 | <% else -%> 76 | * **<%= o[:opt_name] %>**: <%= o[:opt_text] %> 77 | <% end -%> 78 | <% end -%> 79 | 80 | <% end -%> 81 | <% if enums_for_param(param[:name]) -%> 82 | Options: 83 | 84 | <% enums_for_param(param[:name]).each do |e| -%> 85 | * **<%= e[:opt_name] %>**: <%= e[:opt_text] %> 86 | <% end -%> 87 | 88 | <% end -%> 89 | <% if defaults && defaults[param[:name]] -%> 90 | Default value:<%= code_maybe_block(defaults[param[:name]]) %> 91 | 92 | <% end -%> 93 | <% end -%> 94 | <% end -%> 95 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/data_type.erb: -------------------------------------------------------------------------------- 1 | ### `<%= name %>` 2 | 3 | <% if text -%> 4 | <%= text %> 5 | <% elsif summary -%> 6 | <%= summary %> 7 | <% else -%> 8 | <%= "The #{name} data type." %> 9 | <% end -%> 10 | 11 | <% if deprecated -%> 12 | * **DEPRECATED** <%= deprecated %> 13 | 14 | <% end -%> 15 | <% if todo -%> 16 | * **TODO** <%= todo %> 17 | 18 | <% end -%> 19 | <% if note -%> 20 | * **Note** <%= note %> 21 | 22 | <% end -%> 23 | <% if since -%> 24 | * **Since** <%= since %> 25 | 26 | <% end -%> 27 | <% if see -%> 28 | * **See also** 29 | <% see.each do |sa| -%> 30 | <% if sa[:name] -%> 31 | <%= " * #{sa[:name]}" %> 32 | <% end -%> 33 | <% if sa[:text] -%> 34 | <%= " * #{sa[:text]}" %> 35 | <% end -%> 36 | <% end -%> 37 | 38 | <% end -%> 39 | <% if examples -%> 40 | #### Examples 41 | 42 | <% examples.each do |eg| -%> 43 | ##### <%= eg[:name] %> 44 | 45 | ```puppet 46 | <%= eg[:text] %> 47 | ``` 48 | 49 | <% end -%> 50 | <% end -%> 51 | <% if alias_of -%> 52 | Alias of<%= code_maybe_block(alias_of) %> 53 | 54 | <% end -%> 55 | <% if params -%> 56 | #### Parameters 57 | 58 | The following parameters are available in the `<%= name %>` <%= @type %>: 59 | 60 | <% params.each do |param| -%> 61 | * [`<%= param[:name] %>`](#<%= param[:link] %>) 62 | <% end -%> 63 | 64 | <% params.each do |param| -%> 65 | ##### `<%= param[:name] %>` 66 | 67 | <% if param[:types] -%> 68 | Data type:<%= code_maybe_block(param[:types].join(', ')) %> 69 | 70 | <% end -%> 71 | <%= param[:text] %> 72 | 73 | <% if options_for_param(param[:name]) -%> 74 | Options: 75 | 76 | <% options_for_param(param[:name]).each do |o| -%> 77 | * **<%= o[:opt_name] %>** `<%= o[:opt_types][0] %>`: <%= o[:opt_text] %> 78 | <% end -%> 79 | 80 | <% end -%> 81 | <% if enums_for_param(param[:name]) -%> 82 | Options: 83 | 84 | <% enums_for_param(param[:name]).each do |e| -%> 85 | * **<%= e[:opt_name] %>**: <%= e[:opt_text] %> 86 | <% end -%> 87 | 88 | <% end -%> 89 | <% if defaults && defaults[param[:name]] -%> 90 | Default value:<%= code_maybe_block(defaults[param[:name]]) %> 91 | 92 | <% end -%> 93 | <% end -%> 94 | <% end -%> 95 | <% if functions -%> 96 | #### Functions 97 | 98 | The following functions are available in the `<%= name %>` <%= @type %>. 99 | 100 | <% functions.each do |func| -%><%= func.render -%><% end -%> 101 | <% end -%> 102 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/data_type_function.erb: -------------------------------------------------------------------------------- 1 | ### `<%= name %>` 2 | 3 | #### `<%= signature %>` 4 | 5 | <% if text -%> 6 | <%= text %> 7 | 8 | <% elsif summary -%> 9 | <%= summary %> 10 | 11 | <% else -%> 12 | <%= "The #{name} function." %> 13 | 14 | <% end -%> 15 | <% if note -%> 16 | * **Note** <%= note %> 17 | 18 | <% end -%> 19 | <% if return_type -%> 20 | Returns: `<%= return_type %>`<% if return_val %> <%= return_val %><% end %> 21 | 22 | <% end -%> 23 | <% if raises -%> 24 | Raises: 25 | <% raises.each do |r| -%> 26 | * <%= error_type(r[:text]) %> <%= error_text(r[:text]) %> 27 | <% end -%> 28 | 29 | <% end -%> 30 | <% if examples -%> 31 | ##### Examples 32 | 33 | <% examples.each do |eg| -%> 34 | ###### <%= eg[:name] %> 35 | 36 | ```puppet 37 | <%= eg[:text] %> 38 | ``` 39 | 40 | <% end -%> 41 | <% end -%> 42 | <% if params -%> 43 | <% params.each do |param| -%> 44 | ##### `<%= param[:name] %>` 45 | 46 | Data type:<%= code_maybe_block(param[:types][0]) %> 47 | 48 | <%= param[:text] %> 49 | 50 | <% if options_for_param(param[:name]) -%> 51 | Options: 52 | 53 | <% options_for_param(param[:name]).each do |o| -%> 54 | * **<%= o[:opt_name] %>** `<%= o[:opt_types][0] %>`: <%= o[:opt_text] %> 55 | <% end -%> 56 | 57 | <% end -%> 58 | <% if enums_for_param(param[:name]) -%> 59 | Options: 60 | 61 | <% enums_for_param(param[:name]).each do |e| -%> 62 | * **<%= e[:opt_name] %>**: <%= e[:opt_text] %> 63 | <% end -%> 64 | 65 | <% end -%> 66 | <% end -%> 67 | <% end -%> 68 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/function.erb: -------------------------------------------------------------------------------- 1 | ### `<%= name %>` 2 | 3 | Type: <%= type %> 4 | 5 | <% if text -%> 6 | <%= text %> 7 | 8 | <% elsif summary -%> 9 | <%= summary %> 10 | 11 | <% else -%> 12 | <%= "The #{name} function." %> 13 | 14 | <% end -%> 15 | <% if deprecated -%> 16 | * **DEPRECATED** <%= deprecated %> 17 | 18 | <% end -%> 19 | <% if todo -%> 20 | * **TODO** <%= todo %> 21 | 22 | <% end -%> 23 | <% if note -%> 24 | * **Note** <%= note %> 25 | 26 | <% end -%> 27 | <% if examples -%> 28 | #### Examples 29 | 30 | <% examples.each do |eg| -%> 31 | ##### <%= eg[:name] %> 32 | 33 | ```puppet 34 | <%= eg[:text] %> 35 | ``` 36 | 37 | <% end -%> 38 | <% end -%> 39 | <% signatures.each do |sig| -%> 40 | #### `<%= sig.signature %>` 41 | 42 | <% if sig.text -%> 43 | <%= sig.text %> 44 | 45 | <% elsif sig.summary -%> 46 | <%= sig.summary %> 47 | 48 | <% else -%> 49 | <%= "The #{name} function." %> 50 | 51 | <% end -%> 52 | <% if sig.note -%> 53 | * **Note** <%= sig.note %> 54 | 55 | <% end -%> 56 | <% if sig.return_type -%> 57 | Returns: `<%= sig.return_type %>`<% if sig.return_val %> <%= sig.return_val %><% end %> 58 | 59 | <% end -%> 60 | <% if raises -%> 61 | Raises: 62 | 63 | <% raises.each do |r| -%> 64 | * <%= error_type(r[:text]) %> <%= error_text(r[:text]) %> 65 | <% end -%> 66 | 67 | <% end -%> 68 | <% if sig.examples -%> 69 | ##### Examples 70 | 71 | <% sig.examples.each do |eg| -%> 72 | ###### <%= eg[:name] %> 73 | 74 | ```puppet 75 | <%= eg[:text] %> 76 | ``` 77 | 78 | <% end -%> 79 | <% end -%> 80 | <% if sig.params -%> 81 | <% sig.params.each do |param| -%> 82 | ##### `<%= param[:name] %>` 83 | 84 | Data type:<%= code_maybe_block(param[:types][0]) %> 85 | 86 | <%= param[:text] %> 87 | 88 | <% if sig.options_for_param(param[:name]) -%> 89 | Options: 90 | 91 | <% sig.options_for_param(param[:name]).each do |o| -%> 92 | * **<%= o[:opt_name] %>** `<%= o[:opt_types][0] %>`: <%= o[:opt_text] %> 93 | <% end -%> 94 | 95 | <% end -%> 96 | <% if sig.enums_for_param(param[:name]) -%> 97 | Options: 98 | 99 | <% sig.enums_for_param(param[:name]).each do |e| -%> 100 | * **<%= e[:opt_name] %>**: <%= e[:opt_text] %> 101 | <% end -%> 102 | 103 | <% end -%> 104 | <% end -%> 105 | <% end -%> 106 | <% end -%> 107 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/puppet_task.erb: -------------------------------------------------------------------------------- 1 | ### `<%= name %>` 2 | 3 | <% if text -%> 4 | <%= text %> 5 | 6 | <% elsif summary -%> 7 | <%= summary %> 8 | 9 | <% else -%> 10 | <%= "The #{name} task." %> 11 | 12 | <% end -%> 13 | **Supports noop?** <%= supports_noop %> 14 | 15 | <% if params -%> 16 | #### Parameters 17 | 18 | <% params.each do |param| -%> 19 | ##### `<%= param[:name] %>` 20 | 21 | <% if param[:types] -%> 22 | Data type:<%= code_maybe_block(param[:types].join(', ')) %> 23 | 24 | <% end -%> 25 | <%= param[:text] %> 26 | 27 | <% end -%> 28 | <% end -%> 29 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/resource_type.erb: -------------------------------------------------------------------------------- 1 | ### `<%= name %>` 2 | 3 | <% if text -%> 4 | <%= text %> 5 | <% elsif summary -%> 6 | <%= summary %> 7 | <% else -%> 8 | <%= "The #{name} type." %> 9 | <% end -%> 10 | 11 | <% if deprecated -%> 12 | * **DEPRECATED** <%= deprecated %> 13 | 14 | <% end -%> 15 | <% if todo -%> 16 | * **TODO** <%= todo %> 17 | 18 | <% end -%> 19 | <% if note -%> 20 | * **Note** <%= note %> 21 | 22 | <% end -%> 23 | <% if since -%> 24 | * **Since** <%= since %> 25 | 26 | <% end -%> 27 | <% if see -%> 28 | * **See also** 29 | <% see.each do |sa| -%> 30 | <% if sa[:name] -%> 31 | <%= " * #{sa[:name]}" %> 32 | <% end -%> 33 | <% if sa[:text] -%> 34 | <%= " * #{sa[:text]}" %> 35 | <% end -%> 36 | <% end -%> 37 | 38 | <% end -%> 39 | <% if examples -%> 40 | #### Examples 41 | 42 | <% examples.each do |eg| -%> 43 | ##### <%= eg[:name] %> 44 | 45 | ```puppet 46 | <%= eg[:text] %> 47 | ``` 48 | 49 | <% end -%> 50 | <% end -%> 51 | <% if properties_and_checks -%> 52 | #### Properties 53 | 54 | The following properties are available in the `<%= name %>` <%= @type %>. 55 | 56 | <% properties_and_checks.each do |prop| -%> 57 | ##### `<%= prop[:name] %>` 58 | 59 | <% if prop[:values] -%> 60 | Valid values: `<%= prop[:values].join('`, `') %>` 61 | 62 | <% end -%> 63 | <% if prop[:isnamevar] -%> 64 | namevar 65 | 66 | <% end -%> 67 | <% if prop[:aliases] -%> 68 | Aliases: `<%= prop[:aliases].to_s.delete('{').delete('}') %>` 69 | 70 | <% end -%> 71 | <% if prop[:data_type] -%> 72 | Data type: `<%= prop[:data_type] %>`<%= "\n_\*this data type contains a regex that may not be accurately reflected in generated documentation_" if regex_in_data_type?(prop[:data_type]) %> 73 | 74 | <% end -%> 75 | <%= prop[:description] %> 76 | 77 | <% if options_for_param(prop[:name]) -%> 78 | Options: 79 | 80 | <% options_for_param(prop[:name]).each do |o| -%> 81 | * **<%= o[:opt_name] %>** `<%= o[:opt_types][0] %>`: <%= o[:opt_text] %> 82 | <% end -%> 83 | 84 | <% end -%> 85 | <% if enums_for_param(prop[:name]) -%> 86 | Options: 87 | 88 | <% enums_for_param(prop[:name]).each do |e| -%> 89 | * **<%= e[:opt_name] %>**: <%= e[:opt_text] %> 90 | <% end -%> 91 | 92 | <% end -%> 93 | <% if prop[:default] -%> 94 | Default value:<%= code_maybe_block(prop[:default], type: :ruby) %> 95 | 96 | <% end -%> 97 | <% end -%> 98 | <% end -%> 99 | <% if parameters -%> 100 | #### Parameters 101 | 102 | The following parameters are available in the `<%= name %>` <%= @type %>. 103 | 104 | <% parameters.each do |param| -%> 105 | * [`<%= param[:name] %>`](#<%= param[:link] %>) 106 | <% end -%> 107 | 108 | <% parameters.each do |param| -%> 109 | ##### `<%= param[:name] %>` 110 | 111 | <% if param[:values] -%> 112 | Valid values: `<%= param[:values].join('`, `') %>` 113 | 114 | <% end -%> 115 | <% if param[:isnamevar] -%> 116 | namevar 117 | 118 | <% end -%> 119 | <% if param[:aliases] -%> 120 | Aliases: `<%= param[:aliases].to_s.delete('{').delete('}') %>` 121 | 122 | <% end -%> 123 | <% if param[:data_type] -%> 124 | Data type: `<%= param[:data_type] %>`<%= "\n_\*this data type contains a regex that may not be accurately reflected in generated documentation_" if regex_in_data_type?(param[:data_type]) %> 125 | 126 | <% end -%> 127 | <% if param[:description] -%> 128 | <%= word_wrap(param[:description]) %> 129 | <% end -%> 130 | 131 | <% if options_for_param(param[:name]) -%> 132 | Options: 133 | 134 | <% options_for_param(param[:name]).each do |o| -%> 135 | * **<%= o[:opt_name] %>** `<%= o[:opt_types][0] %>`: <%= o[:opt_text] %> 136 | <% end -%> 137 | 138 | <% end -%> 139 | <% if enums_for_param(param[:name]) -%> 140 | Options: 141 | 142 | <% enums_for_param(param[:name]).each do |e| -%> 143 | * **<%= e[:opt_name] %>**: <%= e[:opt_text] %> 144 | <% end -%> 145 | 146 | <% end -%> 147 | <% if param[:default] -%> 148 | Default value: `<%= param[:default] %>` 149 | 150 | <% end -%> 151 | <% if param[:required_features] -%> 152 | Required features: <%= param[:required_features] %>. 153 | 154 | <% end -%> 155 | <% end -%> 156 | <% end -%> 157 | -------------------------------------------------------------------------------- /lib/puppet-strings/markdown/templates/table_of_contents.erb: -------------------------------------------------------------------------------- 1 | <% unless items.empty? -%> 2 | ### <%= group_name %> 3 | <% if has_public -%> 4 | <% if has_private # only display public heading if we have both -%> 5 | 6 | #### Public <%= group_name %> 7 | <% end -%> 8 | 9 | <% items.each do |item| -%> 10 | <% unless item[:private] -%> 11 | * [`<%= item[:name] %>`](#<%= item[:link] %>)<% unless item[:desc].nil? || item[:desc].empty? %>: <%= item[:desc] %><% end %> 12 | <% end -%> 13 | <% end -%> 14 | <% end -%> 15 | <% if has_private -%> 16 | 17 | #### Private <%= group_name %> 18 | 19 | <% items.each do |item| -%> 20 | <% if item[:private] -%> 21 | * `<%= item[:name] %>`<% unless item[:desc].nil? || item[:desc].empty? %>: <%= item[:desc] %><% end %> 22 | <% end -%> 23 | <% end -%> 24 | <% end -%> 25 | 26 | <% end -%> 27 | -------------------------------------------------------------------------------- /lib/puppet-strings/monkey_patches/display_object_command.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Monkey patch URL decoding in object displays. Usually :: is interpreted as a 4 | # namespace, but this is disabled in our base object, and so instead gets 5 | # URL-encoded. 6 | require 'yard/server/commands/display_object_command' 7 | 8 | # Monkey patch YARD::Server::Commands::DisplayObjectCommand object_path. 9 | class YARD::Server::Commands::DisplayObjectCommand 10 | private 11 | 12 | alias object_path_yard object_path 13 | def object_path 14 | object_path_yard.gsub('_3A', ':') 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/puppet-strings/tasks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rake' 4 | require 'rake/tasklib' 5 | 6 | # Ensure PuppetStrings is loaded. 7 | module PuppetStrings end 8 | 9 | # The module for Puppet Strings rake tasks. 10 | module PuppetStrings::Tasks 11 | require 'puppet-strings/tasks/generate' 12 | require 'puppet-strings/tasks/gh_pages' 13 | require 'puppet-strings/tasks/validate' 14 | end 15 | -------------------------------------------------------------------------------- /lib/puppet-strings/tasks/generate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings' 4 | 5 | # Implements the strings:generate task. 6 | namespace :strings do 7 | desc 'Generate Puppet documentation with YARD.' 8 | task :generate, [:patterns, :debug, :backtrace, :markup, :json, :markdown, :yard_args] do |_t, args| 9 | patterns = args[:patterns] 10 | patterns = patterns.split if patterns 11 | patterns ||= PuppetStrings::DEFAULT_SEARCH_PATTERNS 12 | 13 | options = { 14 | debug: args[:debug] == 'true', 15 | backtrace: args[:backtrace] == 'true', 16 | markup: args[:markup] || 'markdown' 17 | } 18 | 19 | raise('Error: Both JSON and Markdown output have been selected. Please select one.') if args[:json] == 'true' && args[:markdown] == 'true' 20 | 21 | # rubocop:disable Style/PreferredHashMethods 22 | # Because of Ruby, true and false from the args are both strings and both true. Here, 23 | # when the arg is set to false (or empty), set it to real false, else real true. Then, 24 | # if the arg is set simply to 'true', assume default behavior is expected and set the path 25 | # to nil to elicit that, else set to the path given. 26 | # @param [Hash] args from the Rake task cli 27 | # @param [Hash] options to send to the generate function 28 | # @param [Symbol] possible format option 29 | # @return nil 30 | def parse_format_option(args, options, format) 31 | return unless args.has_key? format 32 | 33 | options[format] = !(args[format] == 'false' || args[format].empty?) 34 | return unless options[format] 35 | 36 | options[:path] = args[format] == 'true' ? nil : args[format] 37 | end 38 | # rubocop:enable Style/PreferredHashMethods 39 | 40 | %i[json markdown].each { |format| parse_format_option(args, options, format) } 41 | 42 | warn('yard_args behavior is a little dodgy, use at your own risk') if args[:yard_args] 43 | options[:yard_args] = args[:yard_args].split if args.key? :yard_args 44 | 45 | PuppetStrings.generate(patterns, options) 46 | end 47 | 48 | namespace :generate do 49 | desc 'Generate Puppet Reference documentation.' 50 | task :reference, [:patterns, :debug, :backtrace] do |_t, args| 51 | Rake::Task['strings:generate'].invoke(args[:patterns], args[:debug], args[:backtrace], nil, 'false', 'true') 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/puppet-strings/tasks/gh_pages.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'English' 4 | require 'puppet-strings/tasks' 5 | 6 | namespace :strings do 7 | namespace :gh_pages do 8 | task :checkout do 9 | if Dir.exist?('doc') 10 | raise "The 'doc' directory (#{File.expand_path('doc')}) is not a Git repository! Remove it and run the Rake task again." unless Dir.exist?('doc/.git') 11 | 12 | Dir.chdir('doc') do 13 | system 'git checkout gh-pages' 14 | exit 1 unless $?.success? 15 | system 'git pull --rebase origin gh-pages' 16 | exit 1 unless $?.success? 17 | end 18 | else 19 | git_uri = `git config --get remote.origin.url`.strip 20 | raise "Could not determine the remote URL for origin: ensure the current directory is a Git repro with a remote named 'origin'." unless $CHILD_STATUS.success? 21 | 22 | Dir.mkdir('doc') 23 | Dir.chdir('doc') do 24 | system 'git init' 25 | exit 1 unless $?.success? 26 | system "git remote add origin #{git_uri}" 27 | exit 1 unless $?.success? 28 | system 'git pull origin gh-pages' 29 | exit 1 unless $?.success? 30 | system 'git checkout -b gh-pages' 31 | exit 1 unless $?.success? 32 | end 33 | end 34 | end 35 | 36 | task :configure do 37 | unless File.exist?(File.join('doc', '_config.yml')) 38 | Dir.chdir('doc') do 39 | File.write('_config.yml', 'include: _index.html') 40 | end 41 | end 42 | end 43 | 44 | # Task to push the gh-pages branch. Argument :msg_prefix is the beginning 45 | # of the message and the actual commit will have "at Revision " 46 | # appended. 47 | task :push, [:msg_prefix] do |_t, args| 48 | msg_prefix = args[:msg_prefix] || '[strings] Generated Documentation Update' 49 | 50 | output = `git describe --long 2>/dev/null` 51 | # If a project has never been tagged, fall back to latest SHA 52 | git_sha = output.empty? ? `git log --pretty=format:'%H' -n 1` : output 53 | 54 | Dir.chdir('doc') do 55 | system 'git add .' 56 | exit 1 unless $?.success? 57 | system "git commit -m '#{msg_prefix} at Revision #{git_sha}'" 58 | # Do not check status of commit, as it will error if there are no changes. 59 | system 'git push origin gh-pages -f' 60 | exit 1 unless $?.success? 61 | end 62 | end 63 | 64 | desc 'Update docs on the gh-pages branch and push to GitHub.' 65 | task update: %i[ 66 | checkout 67 | strings:generate 68 | configure 69 | push 70 | ] 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/puppet-strings/tasks/validate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings' 4 | require 'tempfile' 5 | 6 | namespace :strings do 7 | namespace :validate do 8 | desc 'Validate the reference is up to date' 9 | task :reference, [:patterns, :debug, :backtrace] do |_t, args| 10 | filename = 'REFERENCE.md' 11 | 12 | unless File.exist?(filename) 13 | warn "#{filename} does not exist" 14 | exit 1 15 | end 16 | 17 | patterns = args[:patterns] 18 | patterns = patterns.split if patterns 19 | patterns ||= PuppetStrings::DEFAULT_SEARCH_PATTERNS 20 | 21 | generated = Tempfile.create do |file| 22 | options = { 23 | debug: args[:debug] == 'true', 24 | backtrace: args[:backtrace] == 'true', 25 | json: false, 26 | markdown: true, 27 | path: file 28 | } 29 | PuppetStrings.generate(patterns, options) 30 | 31 | file.read 32 | end 33 | 34 | existing = File.read(filename) 35 | 36 | if generated != existing 37 | warn "#{filename} is outdated; to regenerate: bundle exec rake strings:generate:reference" 38 | exit 1 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/puppet-strings/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module PuppetStrings 4 | VERSION = '5.0.0' 5 | end 6 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # The module for custom YARD code objects. 4 | module PuppetStrings::Yard::CodeObjects 5 | require 'puppet-strings/yard/code_objects/class' 6 | require 'puppet-strings/yard/code_objects/data_type' 7 | require 'puppet-strings/yard/code_objects/data_type_alias' 8 | require 'puppet-strings/yard/code_objects/defined_type' 9 | require 'puppet-strings/yard/code_objects/type' 10 | require 'puppet-strings/yard/code_objects/provider' 11 | require 'puppet-strings/yard/code_objects/function' 12 | require 'puppet-strings/yard/code_objects/task' 13 | require 'puppet-strings/yard/code_objects/plan' 14 | end 15 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Implements the base code object. 4 | class PuppetStrings::Yard::CodeObjects::Base < YARD::CodeObjects::NamespaceObject 5 | # Allocates a new code object. 6 | # @param [Array] args The arguments to initialize the code object with. 7 | # @return Returns the code object. 8 | def self.new(*args) 9 | # Skip the super class' implementation because it detects :: in names and this will cause namespaces in the output we don't want 10 | object = Object.class.instance_method(:new).bind_call(self, *args) 11 | existing = YARD::Registry.at(object.path) 12 | object = existing if existing.instance_of?(self) 13 | yield(object) if block_given? 14 | object 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/class.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | 5 | # Implements the group for Puppet classes. 6 | class PuppetStrings::Yard::CodeObjects::Classes < PuppetStrings::Yard::CodeObjects::Group 7 | # Gets the singleton instance of the group. 8 | # @return Returns the singleton instance of the group. 9 | def self.instance 10 | super(:puppet_classes) 11 | end 12 | 13 | # Gets the display name of the group. 14 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 15 | # @return [String] Returns the display name of the group. 16 | def name(_prefix = false) 17 | 'Puppet Classes' 18 | end 19 | end 20 | 21 | # Implements the Puppet class code object. 22 | class PuppetStrings::Yard::CodeObjects::Class < PuppetStrings::Yard::CodeObjects::Base 23 | attr_reader :statement, :parameters 24 | 25 | # Initializes a Puppet class code object. 26 | # @param [PuppetStrings::Parsers::ClassStatement] statement The class statement that was parsed. 27 | # @return [void] 28 | def initialize(statement) 29 | @statement = statement 30 | @parameters = statement.parameters.map { |p| [p.name, p.value] } 31 | super(PuppetStrings::Yard::CodeObjects::Classes.instance, statement.name) 32 | end 33 | 34 | # Gets the type of the code object. 35 | # @return Returns the type of the code object. 36 | def type 37 | :puppet_class 38 | end 39 | 40 | # Gets the source of the code object. 41 | # @return Returns the source of the code object. 42 | def source 43 | @statement.source 44 | end 45 | 46 | # Converts the code object to a hash representation. 47 | # @return [Hash] Returns a hash representation of the code object. 48 | def to_hash 49 | hash = {} 50 | hash[:name] = name 51 | hash[:file] = file 52 | hash[:line] = line 53 | hash[:inherits] = statement.parent_class if statement.parent_class 54 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) 55 | defaults = Hash[*parameters.reject { |p| p[1].nil? }.flatten] 56 | hash[:defaults] = defaults unless defaults.nil? || defaults.empty? 57 | hash[:source] = source unless source.nil? || source.empty? 58 | hash 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/data_type.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | require 'puppet-strings/yard/util' 5 | 6 | # Implements the group for Puppet DataTypes. 7 | class PuppetStrings::Yard::CodeObjects::DataTypes < PuppetStrings::Yard::CodeObjects::Group 8 | # Gets the singleton instance of the group. 9 | # @return Returns the singleton instance of the group. 10 | def self.instance 11 | super(:puppet_data_types) 12 | end 13 | 14 | # Gets the display name of the group. 15 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 16 | # @return [String] Returns the display name of the group. 17 | def name(_prefix = false) 18 | 'Puppet Data Types' 19 | end 20 | end 21 | 22 | # Implements the Puppet DataType code object. 23 | class PuppetStrings::Yard::CodeObjects::DataType < PuppetStrings::Yard::CodeObjects::Base 24 | # Initializes a Puppet class code object. 25 | # @param [String] The name of the Data Type 26 | # @return [void] 27 | def initialize(name) 28 | super(PuppetStrings::Yard::CodeObjects::DataTypes.instance, name) 29 | @defaults = {} 30 | end 31 | 32 | # Gets the type of the code object. 33 | # @return Returns the type of the code object. 34 | def type 35 | :puppet_data_type 36 | end 37 | 38 | # Gets the source of the code object. 39 | # @return Returns the source of the code object. 40 | def source 41 | # Not implemented, but would be nice! 42 | nil 43 | end 44 | 45 | def add_parameter(name, type, default) 46 | tag = docstring.tags(:param).find { |item| item.name == name } 47 | if tag.nil? 48 | tag = YARD::Tags::Tag.new(:param, '', nil, name) 49 | docstring.add_tag(tag) 50 | end 51 | type = [type] unless type.is_a?(Array) 52 | tag.types = type if tag.types.nil? 53 | set_parameter_default(name, default) 54 | end 55 | 56 | def set_parameter_default(param_name, default) 57 | defaults.delete(param_name) 58 | defaults[param_name] = default unless default.nil? 59 | end 60 | 61 | def parameters 62 | docstring.tags(:param).map { |tag| [tag.name, defaults[tag.name]] } 63 | end 64 | 65 | def add_function(name, return_type, parameter_types) 66 | meth_obj = YARD::CodeObjects::MethodObject.new(self, name, :class) 67 | 68 | # Add return tag 69 | meth_obj.add_tag(YARD::Tags::Tag.new(:return, '', return_type)) 70 | 71 | # Add parameters 72 | parameter_types.each_with_index do |param_type, index| 73 | meth_obj.add_tag(YARD::Tags::Tag.new(:param, '', [param_type], "param#{index + 1}")) 74 | end 75 | 76 | meths << meth_obj 77 | end 78 | 79 | def functions 80 | meths 81 | end 82 | 83 | # Converts the code object to a hash representation. 84 | # @return [Hash] Returns a hash representation of the code object. 85 | def to_hash 86 | hash = {} 87 | hash[:name] = name 88 | hash[:file] = file 89 | hash[:line] = line 90 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring, %i[param option enum return example]) 91 | hash[:defaults] = defaults unless defaults.nil? || defaults.empty? 92 | hash[:source] = source unless source.nil? || source.empty? 93 | hash[:functions] = functions.map do |func| 94 | { 95 | name: func.name, 96 | signature: func.signature, 97 | docstring: PuppetStrings::Yard::Util.docstring_to_hash(func.docstring, %i[param option enum return example]) 98 | } 99 | end 100 | hash 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/data_type_alias.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | require 'puppet-strings/yard/util' 5 | 6 | # Implements the group for Puppet DataTypeAliases. 7 | class PuppetStrings::Yard::CodeObjects::DataTypeAliases < PuppetStrings::Yard::CodeObjects::Group 8 | # Gets the singleton instance of the group. 9 | # @return Returns the singleton instance of the group. 10 | def self.instance 11 | super(:puppet_data_type_aliases) 12 | end 13 | 14 | # Gets the display name of the group. 15 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 16 | # @return [String] Returns the display name of the group. 17 | def name(_prefix = false) 18 | 'Puppet Data Type Aliases' 19 | end 20 | end 21 | 22 | # Implements the Puppet DataTypeAlias code object. 23 | class PuppetStrings::Yard::CodeObjects::DataTypeAlias < PuppetStrings::Yard::CodeObjects::Base 24 | attr_reader :statement 25 | attr_accessor :alias_of 26 | 27 | # Initializes a Puppet data type alias code object. 28 | # @param [PuppetStrings::Parsers::DataTypeAliasStatement] statement The data type alias statement that was parsed. 29 | # @return [void] 30 | def initialize(statement) 31 | @statement = statement 32 | @alias_of = statement.alias_of 33 | super(PuppetStrings::Yard::CodeObjects::DataTypeAliases.instance, statement.name) 34 | end 35 | 36 | # Gets the type of the code object. 37 | # @return Returns the type of the code object. 38 | def type 39 | :puppet_data_type_alias 40 | end 41 | 42 | # Gets the source of the code object. 43 | # @return Returns the source of the code object. 44 | def source 45 | # Not implemented, but would be nice! 46 | nil 47 | end 48 | 49 | # Converts the code object to a hash representation. 50 | # @return [Hash] Returns a hash representation of the code object. 51 | def to_hash 52 | hash = {} 53 | hash[:name] = name 54 | hash[:file] = file 55 | hash[:line] = line 56 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) 57 | hash[:alias_of] = alias_of 58 | hash 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/defined_type.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | 5 | # Implements the group for Puppet defined types. 6 | class PuppetStrings::Yard::CodeObjects::DefinedTypes < PuppetStrings::Yard::CodeObjects::Group 7 | # Gets the singleton instance of the group. 8 | # @return Returns the singleton instance of the group. 9 | def self.instance 10 | super(:puppet_defined_types) 11 | end 12 | 13 | # Gets the display name of the group. 14 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 15 | # @return [String] Returns the display name of the group. 16 | def name(_prefix = false) 17 | 'Defined Types' 18 | end 19 | end 20 | 21 | # Implements the Puppet defined type code object. 22 | class PuppetStrings::Yard::CodeObjects::DefinedType < PuppetStrings::Yard::CodeObjects::Base 23 | attr_reader :statement, :parameters 24 | 25 | # Initializes a Puppet defined type code object. 26 | # @param [PuppetStrings::Parsers::DefinedTypeStatement] statement The defined type statement that was parsed. 27 | # @return [void] 28 | def initialize(statement) 29 | @statement = statement 30 | @parameters = statement.parameters.map { |p| [p.name, p.value] } 31 | super(PuppetStrings::Yard::CodeObjects::DefinedTypes.instance, statement.name) 32 | end 33 | 34 | # Gets the type of the code object. 35 | # @return Returns the type of the code object. 36 | def type 37 | :puppet_defined_type 38 | end 39 | 40 | # Gets the source of the code object. 41 | # @return Returns the source of the code object. 42 | def source 43 | @statement.source 44 | end 45 | 46 | # Converts the code object to a hash representation. 47 | # @return [Hash] Returns a hash representation of the code object. 48 | def to_hash 49 | hash = {} 50 | hash[:name] = name 51 | hash[:file] = file 52 | hash[:line] = line 53 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) 54 | defaults = Hash[*parameters.reject { |p| p[1].nil? }.flatten] 55 | hash[:defaults] = defaults unless defaults.nil? || defaults.empty? 56 | hash[:source] = source unless source.nil? || source.empty? 57 | hash 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/function.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | 5 | # Implements the group for Puppet functions. 6 | class PuppetStrings::Yard::CodeObjects::Functions < PuppetStrings::Yard::CodeObjects::Group 7 | # Gets the singleton instance of the group. 8 | # @param [Symbol] type The function type to get the group for. 9 | # @return Returns the singleton instance of the group. 10 | def self.instance(type) 11 | super(:"puppet_functions_#{type}") 12 | end 13 | 14 | # Gets the display name of the group. 15 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 16 | # @return [String] Returns the display name of the group. 17 | def name(_prefix = false) 18 | 'Puppet Functions' 19 | end 20 | end 21 | 22 | # Implements the Puppet function code object. 23 | class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObjects::Base 24 | # Identifier for 3.x Ruby API functions 25 | RUBY_3X = :ruby3x 26 | # Identifier for 4.x Ruby API functions 27 | RUBY_4X = :ruby4x 28 | # Identifier for Puppet language functions 29 | PUPPET = :puppet 30 | 31 | attr_accessor :parameters 32 | 33 | # Initializes a Puppet function code object. 34 | # @param [String] name The name of the function. 35 | # @param [Symbol] function_type The type of function (e.g. :ruby3x, :ruby4x, :puppet) 36 | # @return [void] 37 | def initialize(name, function_type) 38 | super(PuppetStrings::Yard::CodeObjects::Functions.instance(function_type), name) 39 | @parameters = [] 40 | @function_type = function_type 41 | end 42 | 43 | # Gets the type of the code object. 44 | # @return Returns the type of the code object. 45 | def type 46 | :puppet_function 47 | end 48 | 49 | # Gets the function type display string. 50 | # @return Returns the function type display string. 51 | def function_type 52 | case @function_type 53 | when RUBY_3X 54 | 'Ruby 3.x API' 55 | when RUBY_4X 56 | 'Ruby 4.x API' 57 | else 58 | 'Puppet Language' 59 | end 60 | end 61 | 62 | # Gets the Puppet signature of the function (single overload only). 63 | # @return [String] Returns the Puppet signature of the function. 64 | def signature 65 | return '' if has_tag? :overload 66 | 67 | tags = self.tags(:param) 68 | args = @parameters.map do |parameter| 69 | name, default = parameter 70 | tag = tags.find { |t| t.name == name } if tags 71 | type = tag&.types ? "#{tag.type} " : 'Any ' 72 | prefix = (name[0]).to_s if name.start_with?('*', '&') 73 | name = name[1..] if prefix 74 | default = " = #{default}" if default 75 | "#{type}#{prefix}$#{name}#{default}" 76 | end.join(', ') 77 | "#{@name}(#{args})" 78 | end 79 | 80 | # Converts the code object to a hash representation. 81 | # @return [Hash] Returns a hash representation of the code object. 82 | def to_hash 83 | hash = {} 84 | 85 | hash[:name] = name 86 | hash[:file] = file 87 | hash[:line] = line 88 | hash[:type] = @function_type.to_s 89 | hash[:signatures] = [] 90 | 91 | if has_tag? :overload 92 | # loop over overloads and append onto the signatures array 93 | tags(:overload).each do |o| 94 | hash[:signatures] << { signature: o.signature, docstring: PuppetStrings::Yard::Util.docstring_to_hash(o.docstring, %i[param option enum return example]) } 95 | end 96 | else 97 | hash[:signatures] << { signature:, docstring: PuppetStrings::Yard::Util.docstring_to_hash(docstring, %i[param option enum return example]) } 98 | end 99 | 100 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) 101 | defaults = Hash[*parameters.reject { |p| p[1].nil? }.flatten] 102 | hash[:defaults] = defaults unless defaults.nil? || defaults.empty? 103 | hash[:source] = source unless source.nil? || source.empty? 104 | hash 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/group.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/base' 4 | 5 | # Implements the base class for "groups". 6 | # 7 | # A group behaves like a YARD namespace object, but displays differently in the HTML output. 8 | class PuppetStrings::Yard::CodeObjects::Group < PuppetStrings::Yard::CodeObjects::Base 9 | # Gets the singleton instance of the group. 10 | # @param [Symbol] key The key to lookup the group for. 11 | # @return Returns the singleton instance of the group. 12 | def self.instance(key) 13 | instance = P(:root, key) 14 | return instance unless instance.is_a?(YARD::CodeObjects::Proxy) 15 | 16 | instance = new(:root, key) 17 | instance.visibility = :hidden 18 | P(:root).children << instance 19 | instance 20 | end 21 | 22 | # Gets the path to the group. 23 | # @return [String] Returns the path to the group. 24 | def path 25 | @name.to_s 26 | end 27 | 28 | # Gets the type of the group. 29 | # @return [Symbol] Returns the type of the group. 30 | def type 31 | @name 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/plan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | 5 | # Implements the group for Puppet plans. 6 | class PuppetStrings::Yard::CodeObjects::Plans < PuppetStrings::Yard::CodeObjects::Group 7 | # Gets the singleton instance of the group. 8 | # @return Returns the singleton instance of the group. 9 | def self.instance 10 | super(:puppet_plans) 11 | end 12 | 13 | # Gets the display name of the group. 14 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 15 | # @return [String] Returns the display name of the group. 16 | def name(_prefix = false) 17 | 'Puppet Plans' 18 | end 19 | end 20 | 21 | # Implements the Puppet plan code object. 22 | class PuppetStrings::Yard::CodeObjects::Plan < PuppetStrings::Yard::CodeObjects::Base 23 | attr_reader :statement, :parameters 24 | 25 | # Initializes a Puppet plan code object. 26 | # @param [PuppetStrings::Parsers::PlanStatement] statement The plan statement that was parsed. 27 | # @return [void] 28 | def initialize(statement) 29 | @statement = statement 30 | @parameters = statement.parameters.map { |p| [p.name, p.value] } 31 | super(PuppetStrings::Yard::CodeObjects::Plans.instance, statement.name) 32 | end 33 | 34 | # Gets the type of the code object. 35 | # @return Returns the type of the code object. 36 | def type 37 | :puppet_plan 38 | end 39 | 40 | # Gets the source of the code object. 41 | # @return Returns the source of the code object. 42 | def source 43 | @statement.source 44 | end 45 | 46 | # Converts the code object to a hash representation. 47 | # @return [Hash] Returns a hash representation of the code object. 48 | def to_hash 49 | hash = {} 50 | hash[:name] = name 51 | hash[:file] = file 52 | hash[:line] = line 53 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) 54 | defaults = Hash[*parameters.reject { |p| p[1].nil? }.flatten] 55 | hash[:defaults] = defaults unless defaults.nil? || defaults.empty? 56 | hash[:source] = source unless source.nil? || source.empty? 57 | hash 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/provider.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | 5 | # Implements the group for Puppet providers. 6 | class PuppetStrings::Yard::CodeObjects::Providers < PuppetStrings::Yard::CodeObjects::Group 7 | # Gets the singleton instance of the group. 8 | # @param [String] type The resource type name for the provider. 9 | # @return Returns the singleton instance of the group. 10 | def self.instance(type) 11 | super(:"puppet_providers_#{type}") 12 | end 13 | 14 | # Gets the display name of the group. 15 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 16 | # @return [String] Returns the display name of the group. 17 | def name(_prefix = false) 18 | 'Providers' 19 | end 20 | end 21 | 22 | # Implements the Puppet provider code object. 23 | class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObjects::Base 24 | attr_reader :type_name, :confines, :features, :defaults, :commands 25 | 26 | # Initializes a Puppet provider code object. 27 | # @param [String] type_name The resource type name for the provider. 28 | # @param [String] name The name of the provider.s 29 | # @return [void] 30 | def initialize(type_name, name) 31 | @type_name = type_name 32 | super(PuppetStrings::Yard::CodeObjects::Providers.instance(type_name), name) 33 | end 34 | 35 | # Gets the type of the code object. 36 | # @return Returns the type of the code object. 37 | def type 38 | :puppet_provider 39 | end 40 | 41 | # Adds a confine to the provider. 42 | # @param [String] key The confine's key. 43 | # @param [String] value The confine's value. 44 | # @return [void] 45 | def add_confine(key, value) 46 | return unless key && value 47 | 48 | @confines ||= {} 49 | @confines[key] = value 50 | end 51 | 52 | # Adds a feature to the provider. 53 | # @param [String] feature The feature to add to the provider. 54 | # @return [void] 55 | def add_feature(feature) 56 | return unless feature 57 | 58 | @features ||= [] 59 | @features << feature 60 | end 61 | 62 | # Adds a default to the provider. 63 | # @param [Array] constraints List of related key-pair values for the default. 64 | # @return [void] 65 | def add_default(constraints) 66 | return unless constraints 67 | 68 | @defaults ||= [] 69 | @defaults << constraints 70 | end 71 | 72 | # Adds a command to the provider. 73 | # @param [String] key The command's key. 74 | # @param [String] value The command's value. 75 | # @return [void] 76 | def add_command(key, value) 77 | return unless key && value 78 | 79 | @commands ||= {} 80 | @commands[key] = value 81 | end 82 | 83 | # Converts the code object to a hash representation. 84 | # @return [Hash] Returns a hash representation of the code object. 85 | def to_hash 86 | hash = {} 87 | hash[:name] = name 88 | hash[:type_name] = type_name 89 | hash[:file] = file 90 | hash[:line] = line 91 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) 92 | hash[:confines] = confines if confines && !confines.empty? 93 | hash[:features] = features if features && !features.empty? 94 | hash[:defaults] = defaults if defaults && !defaults.empty? 95 | hash[:commands] = commands if commands && !commands.empty? 96 | hash 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/code_objects/task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects/group' 4 | 5 | # Implements the group for Puppet tasks. 6 | class PuppetStrings::Yard::CodeObjects::Tasks < PuppetStrings::Yard::CodeObjects::Group 7 | # Gets the singleton instance of the group. 8 | # @return Returns the singleton instance of the group. 9 | def self.instance 10 | super(:puppet_tasks) 11 | end 12 | 13 | # Gets the display name of the group. 14 | # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. 15 | # @return [String] Returns the display name of the group. 16 | def name(_prefix = false) 17 | 'Puppet Tasks' 18 | end 19 | end 20 | 21 | # Implements the Puppet task code object. 22 | class PuppetStrings::Yard::CodeObjects::Task < PuppetStrings::Yard::CodeObjects::Base 23 | attr_reader :statement 24 | 25 | # Initializes a JSON task code object. 26 | # @param statement TaskStatement object 27 | # @return [void] 28 | def initialize(statement) 29 | @name = statement.name 30 | @statement = statement 31 | super(PuppetStrings::Yard::CodeObjects::Tasks.instance, name) 32 | end 33 | 34 | # Gets the type of the code object. 35 | # @return Returns the type of the code object. 36 | def type 37 | :puppet_task 38 | end 39 | 40 | # Gets the source of the code object. 41 | # @return Returns the source of the code object. 42 | def source 43 | @statement.source 44 | end 45 | 46 | def parameters 47 | statement.parameters.map do |name, props| 48 | { name: name.to_s, 49 | tag_name: 'param', 50 | text: props['description'] || '', 51 | types: [props['type']] || '' } 52 | end 53 | end 54 | 55 | # Converts the code object to a hash representation. 56 | # @return [Hash] Returns a hash representation of the code object. 57 | def to_hash 58 | { name: name.to_s, 59 | file: statement.file, 60 | line: statement.line, 61 | docstring: { 62 | text: statement.docstring, 63 | tags: parameters 64 | }, 65 | source: statement.source, 66 | supports_noop: statement.json['supports_noop'] || false, 67 | input_method: statement.json['input_method'] } 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # The module for custom YARD handlers. 4 | module PuppetStrings::Yard::Handlers 5 | # The module for custom Ruby YARD handlers. 6 | module Ruby 7 | require 'puppet-strings/yard/handlers/ruby/data_type_handler' 8 | require 'puppet-strings/yard/handlers/ruby/type_handler' 9 | require 'puppet-strings/yard/handlers/ruby/type_extras_handler' 10 | require 'puppet-strings/yard/handlers/ruby/rsapi_handler' 11 | require 'puppet-strings/yard/handlers/ruby/provider_handler' 12 | require 'puppet-strings/yard/handlers/ruby/function_handler' 13 | end 14 | 15 | # The module for custom JSON YARD handlers. 16 | module JSON 17 | require 'puppet-strings/yard/handlers/json/task_handler' 18 | end 19 | 20 | # The module for custom Puppet YARD handlers. 21 | module Puppet 22 | require 'puppet-strings/yard/handlers/puppet/class_handler' 23 | require 'puppet-strings/yard/handlers/puppet/data_type_alias_handler' 24 | require 'puppet-strings/yard/handlers/puppet/defined_type_handler' 25 | require 'puppet-strings/yard/handlers/puppet/function_handler' 26 | require 'puppet-strings/yard/handlers/puppet/plan_handler' 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Implements a helper that logs a warning if a summary tag has more than 140 characters 4 | module PuppetStrings::Yard::Handlers::Helpers 5 | def self.validate_summary_tag(object) 6 | return unless object.has_tag?(:summary) && object.tag(:summary).text.length > 140 7 | 8 | log.warn "The length of the summary for #{object.type} '#{object.name}' exceeds the recommended limit of 140 characters." 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/json/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Implements the base class for all JSON handlers. 4 | class PuppetStrings::Yard::Handlers::JSON::Base < YARD::Handlers::Base 5 | def self.handles?(statement) 6 | handlers.any? { |handler| statement.is_a?(handler) } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/json/task_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/json/base' 4 | require 'puppet-strings/yard/parsers' 5 | require 'puppet-strings/yard/parsers/json/parser' 6 | 7 | # Implements the handler for JSON task metadata. 8 | class PuppetStrings::Yard::Handlers::JSON::TaskHandler < PuppetStrings::Yard::Handlers::JSON::Base 9 | handles PuppetStrings::Yard::Parsers::JSON::TaskStatement 10 | namespace_only 11 | 12 | process do 13 | object = PuppetStrings::Yard::CodeObjects::Task.new(statement) 14 | register object 15 | 16 | @kind = "Puppet Task #{object.name}." 17 | @statement = statement 18 | 19 | validate_description 20 | validate_params 21 | end 22 | 23 | def validate_description 24 | log.warn "Missing a description for #{@kind}." if @statement.docstring.empty? 25 | end 26 | 27 | def validate_params 28 | return if @statement.parameters.empty? 29 | 30 | @statement.parameters.each do |param, val| 31 | log.warn "Missing description for param '#{param}' in #{@kind}" if val['description'].nil? 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/puppet/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Implements the base handler for Puppet language handlers. 4 | class PuppetStrings::Yard::Handlers::Puppet::Base < YARD::Handlers::Base 5 | # Determine sif the handler handles the given statement. 6 | # @param statement The statement that was parsed. 7 | # @return [Boolean] Returns true if the statement is handled by this handler or false if not. 8 | def self.handles?(statement) 9 | handlers.any? { |handler| statement.is_a?(handler) } 10 | end 11 | 12 | protected 13 | 14 | # Sets the parameter tag types for the given code object. 15 | # This also performs some validation on the parameter tags. 16 | # @param object The code object to set the parameter tag types for. 17 | # @return [void] 18 | def set_parameter_types(object) 19 | # Ensure there is an actual parameter for each parameter tag 20 | tags = object.tags(:param) 21 | tags.each do |tag| 22 | next if statement.parameters.find { |p| tag.name == p.name } 23 | 24 | log.warn "The @param tag for parameter '#{tag.name}' has no matching parameter at #{statement.file}:#{statement.line}." unless %w[name title].include?(tag.name) 25 | end 26 | 27 | # Assign the types for the parameter 28 | statement.parameters.each do |parameter| 29 | tag = tags.find { |t| t.name == parameter.name } 30 | unless tag 31 | log.warn "Missing @param tag for parameter '#{parameter.name}' near #{statement.file}:#{statement.line}." unless object.docstring.empty? 32 | 33 | # Add a tag with an empty docstring 34 | object.add_tag YARD::Tags::Tag.new(:param, '', [parameter.type || 'Any'], parameter.name) 35 | next 36 | end 37 | 38 | # Warn if the parameter type and tag types don't match 39 | if parameter.type && tag.types && !tag.types.empty? && parameter.type != tag.types[0] 40 | log.warn "The type of the @param tag for parameter '#{parameter.name}' " \ 41 | "does not match the parameter type specification near #{statement.file}:#{statement.line}: " \ 42 | 'ignoring in favor of parameter type information.' 43 | end 44 | 45 | if parameter.type 46 | tag.types = [parameter.type] 47 | elsif !tag.types 48 | tag.types = ['Any'] 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/puppet/class_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/puppet/base' 5 | require 'puppet-strings/yard/parsers' 6 | require 'puppet-strings/yard/code_objects' 7 | 8 | # Implements the handler for Puppet classes. 9 | class PuppetStrings::Yard::Handlers::Puppet::ClassHandler < PuppetStrings::Yard::Handlers::Puppet::Base 10 | handles PuppetStrings::Yard::Parsers::Puppet::ClassStatement 11 | 12 | process do 13 | # Register the object 14 | object = PuppetStrings::Yard::CodeObjects::Class.new(statement) 15 | register object 16 | 17 | # Log a warning if missing documentation 18 | log.warn "Missing documentation for Puppet class '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty? 19 | 20 | # Set the parameter types 21 | set_parameter_types(object) 22 | 23 | # Mark the class as public if it doesn't already have an api tag 24 | object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api 25 | 26 | # Warn if a summary longer than 140 characters was provided 27 | PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/puppet/data_type_alias_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/puppet/base' 5 | require 'puppet-strings/yard/parsers' 6 | require 'puppet-strings/yard/code_objects' 7 | 8 | # Implements the handler for Puppet Data Type Alias. 9 | class PuppetStrings::Yard::Handlers::Puppet::DataTypeAliasHandler < PuppetStrings::Yard::Handlers::Puppet::Base 10 | handles PuppetStrings::Yard::Parsers::Puppet::DataTypeAliasStatement 11 | 12 | process do 13 | # Register the object 14 | object = PuppetStrings::Yard::CodeObjects::DataTypeAlias.new(statement) 15 | register object 16 | 17 | # Log a warning if missing documentation 18 | log.warn "Missing documentation for Puppet type alias '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty? 19 | 20 | # Mark the class as public if it doesn't already have an api tag 21 | object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api 22 | 23 | # Warn if a summary longer than 140 characters was provided 24 | PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/puppet/defined_type_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/puppet/base' 5 | require 'puppet-strings/yard/parsers' 6 | require 'puppet-strings/yard/code_objects' 7 | 8 | # Implements the handler for Puppet defined types. 9 | class PuppetStrings::Yard::Handlers::Puppet::DefinedTypeHandler < PuppetStrings::Yard::Handlers::Puppet::Base 10 | handles PuppetStrings::Yard::Parsers::Puppet::DefinedTypeStatement 11 | 12 | process do 13 | # Register the object 14 | object = PuppetStrings::Yard::CodeObjects::DefinedType.new(statement) 15 | register object 16 | 17 | # Log a warning if missing documentation 18 | log.warn "Missing documentation for Puppet defined type '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty? 19 | 20 | # Set the parameter types 21 | set_parameter_types(object) 22 | 23 | # Mark the defined type as public if it doesn't already have an api tag 24 | object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api 25 | 26 | # Warn if a summary longer than 140 characters was provided 27 | PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/puppet/function_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/puppet/base' 5 | require 'puppet-strings/yard/parsers' 6 | require 'puppet-strings/yard/code_objects' 7 | 8 | # Implements the handler for Puppet classes. 9 | class PuppetStrings::Yard::Handlers::Puppet::FunctionHandler < PuppetStrings::Yard::Handlers::Puppet::Base 10 | handles PuppetStrings::Yard::Parsers::Puppet::FunctionStatement 11 | 12 | process do 13 | # Register the object 14 | object = PuppetStrings::Yard::CodeObjects::Function.new(statement.name, PuppetStrings::Yard::CodeObjects::Function::PUPPET) 15 | object.source = statement.source 16 | object.source_type = parser.parser_type 17 | register object 18 | 19 | # Log a warning if missing documentation 20 | log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty? 21 | 22 | # Set the parameter tag types 23 | set_parameter_types(object) 24 | 25 | # Add a return tag 26 | add_return_tag(object, statement.type) 27 | 28 | # Set the parameters on the object 29 | object.parameters = statement.parameters.map { |p| [p.name, p.value] } 30 | 31 | # Mark the class as public if it doesn't already have an api tag 32 | object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api 33 | 34 | # Warn if a summary longer than 140 characters was provided 35 | PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary 36 | end 37 | 38 | private 39 | 40 | def add_return_tag(object, type = nil) 41 | tag = object.tag(:return) 42 | if tag 43 | if (type && tag.types && tag.types.first) && (type != tag.types.first) 44 | log.warn "Documented return type does not match return type in function definition near #{statement.file}:#{statement.line}." 45 | end 46 | 47 | tag.types = type ? [type] : tag.types || ['Any'] 48 | return 49 | end 50 | log.warn "Missing @return tag near #{statement.file}:#{statement.line}." 51 | type ||= 'Any' 52 | object.add_tag YARD::Tags::Tag.new(:return, '', type) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/puppet/plan_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/puppet/base' 5 | require 'puppet-strings/yard/parsers' 6 | require 'puppet-strings/yard/code_objects' 7 | 8 | # Implements the handler for Puppet classes. 9 | class PuppetStrings::Yard::Handlers::Puppet::PlanHandler < PuppetStrings::Yard::Handlers::Puppet::Base 10 | handles PuppetStrings::Yard::Parsers::Puppet::PlanStatement 11 | 12 | process do 13 | # Register the object 14 | object = PuppetStrings::Yard::CodeObjects::Plan.new(statement) 15 | register object 16 | 17 | # Log a warning if missing documentation 18 | log.warn "Missing documentation for Puppet plan '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty? 19 | 20 | # Set the parameter types 21 | set_parameter_types(object) 22 | 23 | # Mark the class as public if it doesn't already have an api tag 24 | object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api 25 | 26 | # Warn if a summary longer than 140 characters was provided 27 | PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/ruby/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'ripper' 4 | 5 | # Implements the base handler for Ruby language handlers. 6 | class PuppetStrings::Yard::Handlers::Ruby::Base < YARD::Handlers::Ruby::Base 7 | # A regular expression for detecting the start of a Ruby heredoc. 8 | # Note: the first character of the heredoc start may have been cut off by YARD. 9 | HEREDOC_START = /^ 1 38 | end 39 | 40 | source 41 | when :regexp_literal 42 | node.source 43 | end 44 | end 45 | 46 | def get_name(statementobject, statementtype) 47 | parameters = statementobject.parameters(false) 48 | raise YARD::Parser::UndocumentableError, "Expected at least one parameter to #{statementtype} at #{statementobject.file}:#{statementobject.line}." if parameters.empty? 49 | 50 | name = node_as_string(parameters.first) 51 | raise YARD::Parser::UndocumentableError, "Expected a symbol or string literal for first parameter but found '#{parameters.first.type}' at #{statement.file}:#{statement.line}." unless name 52 | 53 | name 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/ruby/type_extras_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/ruby/type_base' 5 | require 'puppet-strings/yard/code_objects' 6 | require 'puppet-strings/yard/util' 7 | 8 | # Implements the handler for Puppet resource type newparam/newproperty/ensurable calls written in Ruby. 9 | class PuppetStrings::Yard::Handlers::Ruby::TypeExtrasHandler < PuppetStrings::Yard::Handlers::Ruby::TypeBase 10 | # The default docstring when ensurable is used without given a docstring. 11 | DEFAULT_ENSURABLE_DOCSTRING = 'The basic property that the resource should be in.' 12 | 13 | namespace_only 14 | handles method_call(:newparam) 15 | handles method_call(:newproperty) 16 | handles method_call(:ensurable) 17 | 18 | process do 19 | # Our entry point is a type newproperty/newparam compound statement like this: 20 | # "Puppet::Type.type(:file).newparam(:content) do" 21 | # We want to 22 | # Verify the structure 23 | # Capture the three parameters (e.g. type: 'file', newproperty or newparam?, name: 'source') 24 | # Proceed with collecting data 25 | # Either decorate an existing type object or store for future type object parsing 26 | 27 | # Only accept calls to Puppet::Type.type().newparam/.newproperty 28 | # e.g. "Puppet::Type.type(:file).newparam(:content) do" would yield: 29 | # module_name: "Puppet::Type" 30 | # method1_name: "type" 31 | # typename: "file" 32 | # method2_name: "newparam" 33 | # propertyname: "content" 34 | 35 | return unless (statement.count > 1) && (statement[0].children.count > 2) 36 | 37 | module_name = statement[0].children[0].source 38 | method1_name = statement[0].children.drop(1).find { |c| c.type == :ident }.source 39 | return unless ['Type', 'Puppet::Type'].include?(module_name) && method1_name == 'type' 40 | 41 | # ensurable is syntatic sugar for newproperty 42 | typename = get_name(statement[0], 'Puppet::Type.type') 43 | if caller_method == 'ensurable' 44 | method2_name = 'newproperty' 45 | propertyname = 'ensure' 46 | else 47 | method2_name = caller_method 48 | propertyname = get_name(statement, "Puppet::Type.type().#{method2_name}") 49 | end 50 | 51 | typeobject = get_type_yard_object(typename) 52 | 53 | # node - what should it be here? 54 | node = statement # ?? not sure... test... 55 | 56 | if method2_name == 'newproperty' 57 | typeobject.add_property(create_property(propertyname, node)) 58 | elsif method2_name == 'newparam' 59 | typeobject.add_parameter(create_parameter(propertyname, node)) 60 | end 61 | 62 | # Set the default namevar 63 | set_default_namevar(typeobject) 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/handlers/ruby/type_handler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/handlers/helpers' 4 | require 'puppet-strings/yard/handlers/ruby/type_base' 5 | require 'puppet-strings/yard/code_objects' 6 | require 'puppet-strings/yard/util' 7 | 8 | # Implements the handler for Puppet resource types written in Ruby. 9 | class PuppetStrings::Yard::Handlers::Ruby::TypeHandler < PuppetStrings::Yard::Handlers::Ruby::TypeBase 10 | # The default docstring when ensurable is used without given a docstring. 11 | DEFAULT_ENSURABLE_DOCSTRING = 'The basic property that the resource should be in.' 12 | 13 | namespace_only 14 | handles method_call(:newtype) 15 | 16 | process do 17 | # Only accept calls to Puppet::Type 18 | return unless statement.count > 1 19 | 20 | module_name = statement[0].source 21 | return unless ['Puppet::Type', 'Type'].include?(module_name) 22 | 23 | object = get_type_yard_object(get_name(statement, 'Puppet::Type.newtype')) 24 | 25 | docstring = find_docstring(statement, "Puppet resource type '#{object.name}'") 26 | register_docstring(object, docstring, nil) if docstring 27 | 28 | # Populate the parameters/properties/features to the type 29 | populate_type_data(object) 30 | 31 | # Set the default namevar 32 | set_default_namevar(object) 33 | 34 | # Mark the type as public if it doesn't already have an api tag 35 | object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api 36 | 37 | # Warn if a summary longer than 140 characters was provided 38 | PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary 39 | end 40 | 41 | private 42 | 43 | def populate_type_data(object) 44 | # Traverse the block looking for properties/parameters/features 45 | block = statement.block 46 | return unless block && block.count >= 2 47 | 48 | block[1].children.each do |node| 49 | next unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) && 50 | node.method_name 51 | 52 | method_name = node.method_name.source 53 | parameters = node.parameters(false) 54 | 55 | case method_name 56 | when 'newproperty' 57 | # Add a property to the object 58 | next unless parameters.count >= 1 59 | 60 | name = node_as_string(parameters[0]) 61 | next unless name 62 | 63 | object.add_property(create_property(name, node)) 64 | when 'newparam' 65 | # Add a parameter to the object 66 | next unless parameters.count >= 1 67 | 68 | name = node_as_string(parameters[0]) 69 | next unless name 70 | 71 | object.add_parameter(create_parameter(name, node)) 72 | when 'newcheck' 73 | # Add a check to the object 74 | next unless parameters.count >= 1 75 | 76 | name = node_as_string(parameters[0]) 77 | next unless name 78 | 79 | object.add_check(create_check(name, node)) 80 | when 'feature' 81 | # Add a feature to the object 82 | next unless parameters.count >= 2 83 | 84 | name = node_as_string(parameters[0]) 85 | next unless name 86 | 87 | docstring = node_as_string(parameters[1]) 88 | next unless docstring 89 | 90 | object.add_feature(PuppetStrings::Yard::CodeObjects::Type::Feature.new(name, docstring)) 91 | when 'ensurable' 92 | if node.block 93 | property = create_property('ensure', node) 94 | property.docstring = DEFAULT_ENSURABLE_DOCSTRING if property.docstring.empty? 95 | else 96 | property = PuppetStrings::Yard::CodeObjects::Type::Property.new('ensure', DEFAULT_ENSURABLE_DOCSTRING) 97 | property.add('present') 98 | property.add('absent') 99 | property.default = 'present' 100 | end 101 | object.add_property property 102 | end 103 | end 104 | end 105 | end 106 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/parsers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # The module for custom YARD parsers. 4 | module PuppetStrings::Yard::Parsers 5 | # The module for custom YARD parsers for JSON. 6 | module JSON 7 | require 'puppet-strings/yard/parsers/json/parser' 8 | end 9 | 10 | # The module for custom YARD parsers for the Puppet language. 11 | module Puppet 12 | require 'puppet-strings/yard/parsers/puppet/parser' 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/parsers/json/parser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/parsers/json/task_statement' 4 | 5 | # Implementas a JSON parser. 6 | class PuppetStrings::Yard::Parsers::JSON::Parser < YARD::Parser::Base 7 | attr_reader :file, :source 8 | 9 | # Initializes the parser. 10 | # @param [String] source The source being parsed. 11 | # @param [String] filename The file name of the file being parsed. 12 | # @return [void] 13 | def initialize(source, filename) # rubocop:disable Lint/MissingSuper 14 | @file = filename 15 | @source = source 16 | @statements = [] 17 | end 18 | 19 | def enumerator 20 | @statements 21 | end 22 | 23 | # Parses the source 24 | # @return [void] 25 | def parse 26 | begin 27 | json = JSON.parse(source) 28 | # TODO: this should compare json to a Task metadata json-schema or perform some other hueristics 29 | # to determine what type of statement it represents 30 | @statements.push(PuppetStrings::Yard::Parsers::JSON::TaskStatement.new(json, @source, @file)) unless json.empty? 31 | rescue StandardError 32 | log.error "Failed to parse #{@file}: " 33 | @statements = [] 34 | end 35 | @statements.freeze 36 | self 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/parsers/json/task_statement.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module PuppetStrings::Yard::Parsers::JSON 4 | # Represents the Puppet Task statement. 5 | class TaskStatement 6 | attr_reader :line, :comments_range, :json, :file, :source, :docstring 7 | 8 | def initialize(json, source, file) 9 | @file = file 10 | @source = source 11 | @json = json 12 | @line = 0 13 | @comments_range = nil 14 | @docstring = YARD::Docstring.new(@json['description']) 15 | end 16 | 17 | def parameters 18 | json['parameters'] || {} 19 | end 20 | 21 | def comments_hash_flag 22 | false 23 | end 24 | 25 | def show 26 | '' 27 | end 28 | 29 | def comments 30 | docstring.all 31 | end 32 | 33 | def name 34 | File.basename(@file).gsub('.json', '') || '' 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/parsers/puppet/parser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet' 4 | require 'puppet/pops' 5 | require 'puppet-strings/yard/parsers/puppet/statement' 6 | 7 | # Implements the Puppet language parser. 8 | class PuppetStrings::Yard::Parsers::Puppet::Parser < YARD::Parser::Base 9 | attr_reader :file, :source 10 | 11 | # Initializes the parser. 12 | # @param [String] source The source being parsed. 13 | # @param [String] filename The file name of the file being parsed. 14 | # @return [void] 15 | def initialize(source, filename) # rubocop:disable Lint/MissingSuper 16 | @source = source 17 | @file = filename 18 | @visitor = ::Puppet::Pops::Visitor.new(self, 'transform') 19 | end 20 | 21 | # Parses the source. 22 | # @return [void] 23 | def parse 24 | begin 25 | Puppet[:tasks] = true if Puppet.settings.include?(:tasks) 26 | @statements ||= (@visitor.visit(::Puppet::Pops::Parser::Parser.new.parse_string(source)) || []).compact 27 | rescue ::Puppet::ParseError => e 28 | log.error "Failed to parse #{@file}: #{e.message}" 29 | @statements = [] 30 | end 31 | @statements.freeze 32 | self 33 | end 34 | 35 | # Gets an enumerator for the statements that were parsed. 36 | # @return Returns an enumerator for the statements that were parsed. 37 | def enumerator 38 | @statements 39 | end 40 | 41 | private 42 | 43 | # TODO: Fix the rubocop violations in this file between the following rubocop:disable/enable lines 44 | # rubocop:disable Naming/MethodName 45 | def transform_Program(o) 46 | # Cache the lines of the source text; we'll use this to locate comments 47 | @lines = o.source_text.lines.to_a 48 | o.definitions.map { |d| @visitor.visit(d) } 49 | end 50 | 51 | def transform_Factory(o) 52 | @visitor.visit(o.current) 53 | end 54 | 55 | def transform_HostClassDefinition(o) 56 | statement = PuppetStrings::Yard::Parsers::Puppet::ClassStatement.new(o, @file) 57 | statement.extract_docstring(@lines) 58 | statement 59 | end 60 | 61 | def transform_ResourceTypeDefinition(o) 62 | statement = PuppetStrings::Yard::Parsers::Puppet::DefinedTypeStatement.new(o, @file) 63 | statement.extract_docstring(@lines) 64 | statement 65 | end 66 | 67 | def transform_FunctionDefinition(o) 68 | statement = PuppetStrings::Yard::Parsers::Puppet::FunctionStatement.new(o, @file) 69 | statement.extract_docstring(@lines) 70 | statement 71 | end 72 | 73 | def transform_PlanDefinition(o) 74 | statement = PuppetStrings::Yard::Parsers::Puppet::PlanStatement.new(o, @file) 75 | statement.extract_docstring(@lines) 76 | statement 77 | end 78 | 79 | def transform_TypeAlias(o) 80 | statement = PuppetStrings::Yard::Parsers::Puppet::DataTypeAliasStatement.new(o, @file) 81 | statement.extract_docstring(@lines) 82 | statement 83 | end 84 | 85 | def transform_Object(o) 86 | # Ignore anything else (will be compacted out of the resulting array) 87 | end 88 | # rubocop:enable Naming/MethodName 89 | end 90 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # The module for custom YARD tags. 4 | module PuppetStrings::Yard::Tags 5 | require 'puppet-strings/yard/tags/factory' 6 | require 'puppet-strings/yard/tags/parameter_directive' 7 | require 'puppet-strings/yard/tags/property_directive' 8 | require 'puppet-strings/yard/tags/overload_tag' 9 | require 'puppet-strings/yard/tags/summary_tag' 10 | require 'puppet-strings/yard/tags/enum_tag' 11 | end 12 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags/enum_tag.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'yard/tags/option_tag' 4 | 5 | # Implements an enum tag for describing enumerated value data types 6 | class PuppetStrings::Yard::Tags::EnumTag < YARD::Tags::OptionTag 7 | # Registers the tag with YARD. 8 | # @return [void] 9 | def self.register! 10 | YARD::Tags::Library.define_tag('puppet.enum', :enum, :with_enums) 11 | YARD::Tags::Library.visible_tags.place(:enum).after(:option) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags/factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'yard/tags/default_factory' 4 | require 'puppet-strings/yard/tags/enum_tag' 5 | 6 | # Factory for creating tags. 7 | class PuppetStrings::Yard::Tags::Factory < YARD::Tags::DefaultFactory 8 | # Parses tag text and creates a new enum tag type. Modeled after 9 | # the parse_tag_with_options method in YARD::Tags::DefaultFactory. 10 | # 11 | # @param tag_name the name of the tag to parse 12 | # @param [String] text the raw tag text 13 | # @return [Tag] a tag object with the tag_name, name, and nested Tag as type 14 | def parse_tag_with_enums(tag_name, text) 15 | name, text = *extract_name_from_text(text) 16 | PuppetStrings::Yard::Tags::EnumTag.new(tag_name, name, parse_tag_with_name(tag_name, text)) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags/overload_tag.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Implements an overload tag for Puppet functions 4 | # 5 | # This differs from Yard's overload tag in that the signatures are formatted according to Puppet language rules. 6 | class PuppetStrings::Yard::Tags::OverloadTag < YARD::Tags::Tag 7 | attr_reader :parameters, :docstring 8 | 9 | # Initializes the overload tag. 10 | # @param [String, Symbol] name The name of the function being overloaded. 11 | # @param [String] docstring The docstring for the overload. 12 | # @return [void] 13 | def initialize(name, docstring) 14 | super(:overload, nil) 15 | @name = name.to_s 16 | @parameters = [] 17 | @docstring = YARD::Docstring.new(docstring) 18 | end 19 | 20 | # Gets the signature of the overload. 21 | # @return [String] Returns the signature of the overload. 22 | def signature 23 | tags = self.tags(:param) 24 | args = @parameters.map do |parameter| 25 | name, default = parameter 26 | tag = tags.find { |t| t.name == name } if tags 27 | type = tag&.types ? "#{tag.type} " : 'Any ' 28 | prefix = (name[0]).to_s if name.start_with?('*', '&') 29 | name = name[1..] if prefix 30 | default = " = #{default}" if default 31 | "#{type}#{prefix}$#{name}#{default}" 32 | end.join(', ') 33 | "#{@name}(#{args})" 34 | end 35 | 36 | # Adds a tag to the overload's docstring. 37 | # @param [YARD::Tag] tag The tag to add to the overload's docstring. 38 | # @return [void] 39 | def add_tag(tag) 40 | @docstring.add_tag(tag) 41 | end 42 | 43 | # Gets the first tag of the given name. 44 | # @param [String, Symbol] name The name of the tag. 45 | # @return [YARD::Tag] Returns the first tag if found or nil if not found. 46 | def tag(name) 47 | @docstring.tag(name) 48 | end 49 | 50 | # Gets all tags or tags of a given name. 51 | # @param [String, Symbol] name The name of the tag to get or nil for all tags. 52 | # @return [Array] Returns an array of tags. 53 | def tags(name = nil) 54 | @docstring.tags(name) 55 | end 56 | 57 | # Determines if a tag with the given name is present. 58 | # @param [String, Symbol] name The tag name. 59 | # @return [Boolean] Returns true if there is at least one tag with the given name or false if not. 60 | def has_tag?(name) # rubocop:disable Naming/PredicateName 61 | @docstring.has_tag?(name) 62 | end 63 | 64 | # Sets the object associated with this tag. 65 | # @param [Object] value The object to associate with this tag. 66 | # @return [void] 67 | def object=(value) 68 | super 69 | @docstring.object = value 70 | @docstring.tags.each { |tag| tag.object = value } 71 | end 72 | 73 | # Responsible for forwarding method calls to the associated object. 74 | # @param [Symbol] method_name The method being invoked. 75 | # @param [Array] args The args passed to the method. 76 | # @param block The block passed to the method. 77 | # @return Returns what the method call on the object would return. 78 | def method_missing(method_name, ...) 79 | return object.send(method_name, ...) if object.respond_to? method_name 80 | 81 | super 82 | end 83 | 84 | # Determines if the associated object responds to the give missing method name. 85 | # @param [Symbol, String] method_name The name of the method to check. 86 | # @param [Boolean] include_all True to include all methods in the check or false for only public methods. 87 | # @return [Boolean] Returns true if the object responds to the method or false if not. 88 | def respond_to_missing?(method_name, include_all = false) 89 | object.respond_to?(method_name, include_all) || super 90 | end 91 | 92 | # Gets the type of the object associated with this tag. 93 | # @return [Symbol] Returns the type of the object associated with this tag. 94 | def type 95 | object.type 96 | end 97 | 98 | # Converts the overload tag to a hash representation. 99 | # @return [Hash] Returns a hash representation of the overload. 100 | def to_hash 101 | hash = {} 102 | hash[:tag_name] = tag_name 103 | hash[:text] = text if text 104 | hash[:signature] = signature 105 | hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring) unless docstring.blank? 106 | defaults = Hash[*parameters.reject { |p| p[1].nil? }.flatten] 107 | hash[:defaults] = defaults unless defaults.empty? 108 | hash[:types] = types if types 109 | hash[:name] = name if name 110 | hash 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags/parameter_directive.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects' 4 | 5 | # Implements a parameter directive (e.g. #@!puppet.type.param) for documenting Puppet resource types. 6 | class PuppetStrings::Yard::Tags::ParameterDirective < YARD::Tags::Directive 7 | # Called to invoke the directive. 8 | # @return [void] 9 | def call 10 | return unless object.respond_to?(:add_parameter) 11 | 12 | # Add a parameter to the resource 13 | parameter = PuppetStrings::Yard::CodeObjects::Type::Parameter.new(tag.name, tag.text) 14 | tag.types&.each do |value| 15 | parameter.add(value) 16 | end 17 | object.add_parameter parameter 18 | end 19 | 20 | # Registers the directive with YARD. 21 | # @return [void] 22 | def self.register! 23 | YARD::Tags::Library.define_directive('puppet.type.param', :with_types_and_name, self) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags/property_directive.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet-strings/yard/code_objects' 4 | 5 | # Implements a parameter directive (e.g. #@!puppet.type.property) for documenting Puppet resource types. 6 | class PuppetStrings::Yard::Tags::PropertyDirective < YARD::Tags::Directive 7 | # Called to invoke the directive. 8 | # @return [void] 9 | def call 10 | return unless object.respond_to?(:add_property) 11 | 12 | # Add a property to the resource 13 | property = PuppetStrings::Yard::CodeObjects::Type::Property.new(tag.name, tag.text) 14 | tag.types&.each do |value| 15 | property.add(value) 16 | end 17 | object.add_property property 18 | end 19 | 20 | # Registers the directive with YARD. 21 | # @return [void] 22 | def self.register! 23 | YARD::Tags::Library.define_directive('puppet.type.property', :with_types_and_name, self) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/tags/summary_tag.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Implements a summary tag for general purpose short descriptions 4 | class PuppetStrings::Yard::Tags::SummaryTag < YARD::Tags::Tag 5 | # Registers the tag with YARD. 6 | # @return [void] 7 | def self.register! 8 | YARD::Tags::Library.define_tag('puppet.summary', :summary) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/css/common.css: -------------------------------------------------------------------------------- 1 | /* Ensure the search bar doesn't overlap with links */ 2 | .fixed_header { 3 | padding-bottom: 25px; 4 | } 5 | 6 | #full_list { 7 | padding-top: 15px; 8 | } 9 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(true)) %> 6 |
    7 |
  • 8 | <% even = !even %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_data_type.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(false)) %> 6 | <% if item.type == :puppet_data_type_alias %>Alias<% end %> 7 |
    8 |
  • 9 | <% even = !even %> 10 | <% end %> 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(true)) %> 6 |
    7 |
  • 8 | <% even = !even %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(false)) %> 6 | <%= item.function_type %> 7 |
    8 |
  • 9 | <% even = !even %> 10 | <% end %> 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_plan.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(true)) %> 6 |
    7 |
  • 8 | <% even = !even %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(true)) %> 6 | Resource type: <%=item.type_name%> 7 |
    8 |
  • 9 | <% even = !even %> 10 | <% end %> 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_task.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(true)) %> 6 |
    7 |
  • 8 | <% even = !even %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb: -------------------------------------------------------------------------------- 1 | <% even = false %> 2 | <% @items.each do |item| %> 3 |
  • 4 |
    5 | <%= linkify item, h(item.name(true)) %> 6 |
    7 |
  • 8 | <% even = !even %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Generates the searchable Puppet class list. 4 | # @return [void] 5 | def generate_puppet_class_list 6 | @items = Registry.all(:puppet_class).sort_by { |c| c.name.to_s } 7 | @list_title = 'Puppet Class List' 8 | @list_type = 'puppet_class' 9 | generate_list_contents 10 | end 11 | 12 | # Generates the searchable Puppet data type list. 13 | # @return [void] 14 | def generate_puppet_data_type_list 15 | @items = Registry.all(:puppet_data_type, :puppet_data_type_alias).sort_by { |dt| dt.name.to_s } 16 | @list_title = 'Data Type List' 17 | @list_type = 'puppet_data_type' 18 | generate_list_contents 19 | end 20 | 21 | # Generates the searchable Puppet defined type list. 22 | # @return [void] 23 | def generate_puppet_defined_type_list 24 | @items = Registry.all(:puppet_defined_type).sort_by { |dt| dt.name.to_s } 25 | @list_title = 'Defined Type List' 26 | @list_type = 'puppet_defined_type' 27 | generate_list_contents 28 | end 29 | 30 | # Generates the searchable Puppet resource type list. 31 | # @return [void] 32 | def generate_puppet_type_list 33 | @items = Registry.all(:puppet_type).sort_by { |t| t.name.to_s } 34 | @list_title = 'Resource Type List' 35 | @list_type = 'puppet_type' 36 | generate_list_contents 37 | end 38 | 39 | # Generates the searchable Puppet provider list. 40 | # @return [void] 41 | def generate_puppet_provider_list 42 | @items = Registry.all(:puppet_provider).sort_by { |p| p.name.to_s } 43 | @list_title = 'Provider List' 44 | @list_type = 'puppet_provider' 45 | generate_list_contents 46 | end 47 | 48 | # Generates the searchable Puppet function list. 49 | # @return [void] 50 | def generate_puppet_function_list 51 | @items = Registry.all(:puppet_function).sort_by { |f| f.name.to_s } 52 | @list_title = 'Puppet Function List' 53 | @list_type = 'puppet_function' 54 | generate_list_contents 55 | end 56 | 57 | # Generates the searchable Ruby method list. 58 | # @return [void] 59 | def generate_method_list 60 | @items = prune_method_listing(Registry.all(:method), false) 61 | @items = @items.reject { |m| m.name.to_s =~ /=$/ && m.is_attribute? } 62 | @items = @items.sort_by { |m| m.name.to_s } 63 | @list_title = 'Ruby Method List' 64 | @list_type = 'method' 65 | generate_list_contents 66 | end 67 | 68 | # Generate a searchable Ruby class list in the output. 69 | # @return [void] 70 | def generate_class_list 71 | @items = options.objects if options.objects 72 | @list_title = 'Ruby Class List' 73 | @list_type = 'class' 74 | generate_list_contents 75 | end 76 | 77 | # Generates the searchable Puppet Task list. 78 | # @return [void] 79 | def generate_puppet_task_list 80 | @items = Registry.all(:puppet_task).sort_by { |t| t.name.to_s } 81 | @list_title = 'Puppet Task List' 82 | @list_type = 'puppet_task' 83 | generate_list_contents 84 | end 85 | 86 | # Generates the searchable Puppet Plan list. 87 | # @return [void] 88 | def generate_puppet_plan_list 89 | @items = Registry.all(:puppet_plan).sort_by { |t| t.name.to_s } 90 | @list_title = 'Puppet Plan List' 91 | @list_type = 'puppet_plan' 92 | generate_list_contents 93 | end 94 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/layout/html/footer.erb: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/layout/html/objects.erb: -------------------------------------------------------------------------------- 1 | <% unless @objects_by_letter.empty? %> 2 |

    <%= @title %>

    3 | 4 | <% i = 0 %> 5 | 6 | 7 | 11 | 35 | 36 |
    8 | <% @objects_by_letter.sort_by {|l,o| l.to_s }.each do |letter, objects| %> 9 | <% if (i += 1) % 8 == 0 %> 10 | 12 | <% i = 0 %> 13 | <% end %> 14 |
      15 |
    • <%= letter %>
    • 16 |
        17 | <% objects.each do |obj| %> 18 |
      • 19 | <%= linkify obj, obj.name %> 20 | <% if (obj.type == :module || obj.type == :class) && !obj.namespace.root? %> 21 | (<%= obj.namespace.path %>) 22 | <% elsif obj.type == :puppet_provider %> 23 | (Resource type: <%= obj.type_name %>) 24 | <% elsif obj.type == :puppet_function %> 25 | (<%= obj.function_type %>) 26 | <% elsif obj.type == :puppet_data_type_alias %> 27 | (Alias) 28 | <% end %> 29 |
      • 30 | <% end %> 31 |
      32 |
    33 | <% end %> 34 |
    37 | <% end %> 38 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 | <% if object.statement.parent_class %> 3 |
    4 |
    Inherits:
    5 |
    <%= linkify(Registry["puppet_classes::#{object.statement.parent_class}"], object.statement.parent_class.dup) %>
    6 |
    7 | <% end %> 8 | <% if @subclasses && !@subclasses.empty? %> 9 |
    10 |
    Inherited by:
    11 |
    12 | <% @subclasses.each do |subclass| %> 13 | <%= linkify(subclass, subclass.name.to_s) %>
    14 | <% end %> 15 |
    16 |
    17 | <% end %> 18 |
    19 |
    Defined in:
    20 |
    21 | <%= object.file %><% if object.files.size > 1 %>,
    22 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    23 | <% end %> 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Puppet Class: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, :note, :todo, :deprecated, T('tags'), :source 7 | end 8 | 9 | # Renders the box_info section. 10 | # @return [String] Returns the rendered section. 11 | def box_info 12 | @subclasses = Registry.all(:puppet_class).find_all do |c| 13 | c.statement.parent_class == object.name.to_s 14 | end 15 | erb(:box_info) 16 | end 17 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/source.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 | 10 | 11 |
    5 |
    <%= "\n\n\n" %><%= h format_lines(object) %>
    6 |
    8 |
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    9 |
    12 |
    13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_class/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Puppet Data Type: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/method_details_list.erb: -------------------------------------------------------------------------------- 1 |

    Data Type Functions

    2 | <% method_listing.each_with_index do |meth, i| %> 3 |

    <%= meth.name %>

    4 | <%= yieldall :object => meth, :owner => object, :index => i %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, :note, :todo, :deprecated, T('tags'), :method_details_list, [T('method_details')], :source 7 | end 8 | 9 | def method_listing 10 | sort_listing(object.functions) 11 | end 12 | 13 | def sort_listing(list) 14 | list.sort_by { |o| [o.scope.to_s, o.name.to_s.downcase] } 15 | end 16 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/source.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 | 10 | 11 |
    5 |
    <%= "\n\n\n" %><%= h format_lines(object) %>
    6 |
    8 |
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    9 |
    12 |
    13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/alias_of.erb: -------------------------------------------------------------------------------- 1 | <% if @alias_of && !@alias_of.empty? %> 2 |
    3 |

    <%= @tag_title %>

    4 |
    5 |
    6 |
    <%= @alias_of %>
    7 |
    8 |
    9 |
    10 | <% end %> 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Puppet Data Type Alias: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, :alias_of, :note, :todo, :deprecated, T('tags'), :source 7 | end 8 | 9 | # Renders the alias_of section. 10 | # @return [String] Returns the rendered section. 11 | def alias_of 12 | # Properties are the same thing as parameters (from the documentation standpoint), 13 | # so reuse the same template but with a different title and data source. 14 | # @parameters = object.properties || [] 15 | # @parameters.sort_by! { |p| p.name } 16 | @tag_title = 'Alias of' 17 | @alias_of = object.alias_of 18 | erb(:alias_of) 19 | end 20 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/source.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 | 10 | 11 |
    5 |
    <%= "\n\n\n" %><%= h format_lines(object) %>
    6 |
    8 |
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    9 |
    12 |
    13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Defined Type: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, :note, :todo, :deprecated, T('tags'), :source 7 | end 8 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/source.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 | 10 | 11 |
    5 |
    <%= "\n\n\n" %><%= h format_lines(object) %>
    6 |
    8 |
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    9 |
    12 |
    13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_defined_type/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 |
    11 |
    Function type:
    12 |
    <%= object.function_type %>
    13 |
    14 | 15 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Puppet Function: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 | <% unless object.has_tag? :overload %> 4 |
    5 | 6 | 7 | <%= "#{h(object.signature)} ⇒ #{signature_types(object, false)}" %> 8 | 9 | 10 |
    11 | <% end %> 12 |
    13 |
    14 | <%= htmlify(object.docstring) %> 15 |
    16 |
    17 | <%= yieldall %> 18 |
    19 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, [:note, :todo, :deprecated, T('tags'), :source] 7 | end 8 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 | 10 | 11 |
    5 |
    <%= "\n\n\n" %><%= h format_lines(object) %>
    6 |
    8 |
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    9 |
    12 |
    13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_function/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Puppet Plan: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, :note, :todo, :deprecated, T('tags'), :source 7 | end 8 | 9 | # Renders the box_info section. 10 | # @return [String] Returns the rendered section. 11 | def box_info 12 | erb(:box_info) 13 | end 14 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/source.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 | 10 | 11 |
    5 |
    <%= "\n\n\n" %><%= h format_lines(object) %>
    6 |
    8 |
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    9 |
    12 |
    13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_plan/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 |
    11 |
    Resource type:
    12 |
    <%= linkify(Registry["puppet_types::#{object.type_name}"], object.type_name) %>
    13 |
    14 | 15 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/collection.erb: -------------------------------------------------------------------------------- 1 | <% if @collection && !@collection.empty? %> 2 |
    3 |

    <%= @title %>

    4 |
      5 | 6 | <% if @collection.is_a?(Hash) %> 7 | <% @collection.each do |key, value| %> 8 |
    • <%= key %> — <%= value %>
    • 9 | <% end %> 10 | <% elsif @collection.is_a?(Array) %> 11 | <% @collection.each do |kvps| %> 12 |
    • <%= kvps.map{|k,v| "#{k} — #{v}"}.join(', ') %>
    • 13 | <% end %> 14 | <% end %> 15 |
    16 |
    17 | <% end %> 18 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/features.erb: -------------------------------------------------------------------------------- 1 | <% if object.features && !object.features.empty? %> 2 |
    3 |

    Features

    4 |
      5 | <% object.features.each do |feature| %> 6 |
    • 7 | <%= feature %> 8 |
    • 9 | <% end %> 10 |
    11 |
    12 | <% end %> 13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Provider: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, T('tags'), :features, :confines, :defaults, :commands 7 | end 8 | 9 | # Renders the confines section. 10 | # @return [String] Returns the rendered section. 11 | def confines 12 | @title = 'Confines' 13 | @collection = object.confines 14 | erb(:collection) 15 | end 16 | 17 | # Renders the defaults section. 18 | # @return [String] Returns the rendered section. 19 | def defaults 20 | @title = 'Default Provider For' 21 | @collection = object.defaults 22 | erb(:collection) 23 | end 24 | 25 | # Renders the commands section. 26 | # @return [String] Returns the rendered section. 27 | def commands 28 | @title = 'Commands' 29 | @collection = object.commands 30 | erb(:collection) 31 | end 32 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_provider/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %>,
    6 | <%= object.file.gsub('json','rb') %>
    7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Puppet Task: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/input.erb: -------------------------------------------------------------------------------- 1 | <% if json['input_method'] || json['supports_noop'] %> 2 |
    3 |

    Supports noop? <%= json['supports_noop'] ? "true" : "false" %>

    4 |
    5 | <% end %> 6 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= description %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/parameters.erb: -------------------------------------------------------------------------------- 1 | <% if @parameters && !@parameters.empty? %> 2 |
    3 |

    <%= @tag_title %>

    4 |
      5 | <% @parameters.each do |parameter, values| %> 6 |
    • 7 | <%= parameter %> 8 | 9 | (<%= values['type'] %>) 10 | 11 | <% if values['description'] %> — <%= values['description'] %><% end %> 12 |
    • 13 | <% end %> 14 |
    15 |
    16 | <% end %> 17 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, T('tags'), :overview, :input, :parameters 7 | end 8 | 9 | def json 10 | object.statement.json 11 | end 12 | 13 | def description 14 | json['description'] 15 | end 16 | 17 | # Renders the parameters section. 18 | # @return [String] Returns the rendered section. 19 | def parameters 20 | @parameters = json['parameters'] || [] 21 | @parameters.to_a.sort! 22 | @tag_title = 'Parameters' 23 | erb(:parameters) 24 | end 25 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_task/html/supports_noop.erb: -------------------------------------------------------------------------------- 1 | <% if json['supports_noop'] %> 2 | Supports noop? <%= json['supports_noop'] %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/box_info.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    Defined in:
    4 |
    5 | <%= object.file %><% if object.files.size > 1 %>,
    6 | <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    7 | <% end %> 8 | 9 | 10 | <% if @providers && !@providers.empty? %> 11 |
    12 |
    Providers:
    13 |
    14 | <% @providers.each do |provider| %> 15 | <%= linkify(provider, provider.name.to_s) %>
    16 | <% end %> 17 |
    18 |
    19 | <% end %> 20 | 21 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/deprecated.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:deprecated).each do |tag| %> 2 |
    3 | DEPRECATED: 4 | <%= htmlify_line deprecated.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/features.erb: -------------------------------------------------------------------------------- 1 | <% if object.features && !object.features.empty? %> 2 |
    3 |

    Features

    4 |
      5 | <% object.features.each do |feature| %> 6 |
    • 7 | <%= feature.name %> 8 | <% unless feature.docstring.empty? %> — <%= htmlify_line(feature.docstring) %><% end %> 9 |
    • 10 | <% end %> 11 |
    12 |
    13 | <% end %> 14 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/header.erb: -------------------------------------------------------------------------------- 1 |

    Resource Type: <%= object.name %>

    2 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/note.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:note).each do |tag| %> 2 |
    3 | Note: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/overview.erb: -------------------------------------------------------------------------------- 1 |

    Overview

    2 |
    3 |
    4 | <%= htmlify(object.docstring) %> 5 |
    6 |
    7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/parameters.erb: -------------------------------------------------------------------------------- 1 | <% if @parameters && !@parameters.empty? %> 2 |
    3 |

    <%= @tag_title %>

    4 |
      5 | <% @parameters.each do |parameter| %> 6 |
    • 7 | <%= parameter.name + (parameter.isnamevar ? ' (namevar)' : '') %> 8 | <% if parameter.default %> 9 | (defaults to: <%= parameter.default %>) 10 | <% end %> 11 | <% unless parameter.docstring.empty? %> 12 |
      13 |
      14 | <%= htmlify(parameter.docstring) %> 15 |
      16 |
      17 | <% end %> 18 | <% unless parameter.values.empty? %> 19 |
      20 | Supported values: 21 |
        22 | <% parameter.values.each do |value| %> 23 |
      • 24 | <% other = parameter.aliases[value] %> 25 | <%= value %><% if other %> (alias for: <%= other %>)<% end %> 26 |
      • 27 | <% end %> 28 |
      29 |
      30 | <% end %> 31 |
    • 32 | <% end %> 33 |
    34 |
    35 | <% end %> 36 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Initializes the template. 4 | # @return [void] 5 | def init 6 | sections :header, :box_info, :summary, :overview, :note, :todo, :deprecated, T('tags'), :properties, :parameters, :features 7 | end 8 | 9 | # Renders the box_info section. 10 | # @return [String] Returns the rendered section. 11 | def box_info 12 | @providers = PuppetStrings::Yard::CodeObjects::Providers.instance(object.name).children 13 | erb(:box_info) 14 | end 15 | 16 | # Renders the properties section. 17 | # @return [String] Returns the rendered section. 18 | def properties 19 | # Properties are the same thing as parameters (from the documentation standpoint), 20 | # so reuse the same template but with a different title and data source. 21 | # 22 | # "checks" such as "creates" and "onlyif" are another type of property 23 | @parameters = (object.properties || []) + (object.checks || []) 24 | @parameters.sort_by!(&:name) 25 | @tag_title = 'Properties' 26 | erb(:parameters) 27 | end 28 | 29 | # Renders the parameters section. 30 | # @return [String] Returns the rendered section. 31 | def parameters 32 | @parameters = object.parameters || [] 33 | @parameters.sort_by!(&:name) 34 | @tag_title = 'Parameters' 35 | erb(:parameters) 36 | end 37 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/summary.erb: -------------------------------------------------------------------------------- 1 | <% if object.docstring.has_tag?(:summary) %> 2 |

    Summary

    3 | <%= object.docstring.tag(:summary).text %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/puppet_type/html/todo.erb: -------------------------------------------------------------------------------- 1 | <% object.tags(:todo).each do |tag| %> 2 |
    3 | TODO: 4 | <%= htmlify_line tag.text %> 5 |
    6 | <% end %> 7 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/tags/html/enum.erb: -------------------------------------------------------------------------------- 1 | <% if object.has_tag?(:enum) %> 2 | <% object.parameters.each do |param, default| %> 3 | <% tags = object.tags(:enum).select {|x| x.name.to_s == param.to_s.sub(/^\*+|:$/, '') } %> 4 | <% next if tags.empty? %> 5 |

    Enum Options (<%= param %>):

    6 |
      7 | <% for tag in tags %> 8 |
    • 9 | <%= tag.pair.name %> 10 | <% if tag.pair.text && tag.pair.text =~ /\S/ %> 11 | — <%= htmlify_line(tag.pair.text) %> 12 | <% end %> 13 |
    • 14 | <% end %> 15 |
    16 | <% end %> 17 | <% end %> 18 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb: -------------------------------------------------------------------------------- 1 | <% if object.has_tag?(:overload) && object.tags(:overload).any? {|o| !o.docstring.blank? } %> 2 |

    Signatures:

    3 |
      4 | <% object.tags(:overload).each_with_index do |overload, index| %> 5 | <% next if overload.docstring.blank? %> 6 |
    • 7 | <%= "#{h(overload.signature)} ⇒ #{signature_types(overload, false)}" %> 8 | <%= yieldall :object => overload %> 9 |
    • 10 | <% end %> 11 |
    12 | <% end %> 13 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/templates/default/tags/setup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Called to return parameter tags. 4 | # @return [Array] Returns the parameter tags if the object should have parameters. 5 | def param 6 | tag(:param) if 7 | %i[method puppet_class puppet_data_type puppet_defined_type puppet_function puppet_task puppet_plan].include?(object.type) 8 | end 9 | 10 | # Renders the overload section. 11 | # @return [String] Returns the rendered section. 12 | def overload 13 | erb(object.type == :puppet_function ? :puppet_overload : :overload) 14 | end 15 | 16 | # Renders the enum section. 17 | # @return [String] Returns the rendered section. 18 | def enum 19 | erb(:enum) 20 | end 21 | -------------------------------------------------------------------------------- /lib/puppet-strings/yard/util.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/util' 4 | 5 | # The module for various puppet-strings utility helpers. 6 | module PuppetStrings::Yard::Util 7 | # Trims indentation from trailing whitespace and removes ruby literal quotation 8 | # syntax `%Q{}` and `%{q}` from parsed strings. 9 | # @param [String] str The string to scrub. 10 | # @return [String] A scrubbed string. 11 | def self.scrub_string(str) 12 | match = str.match(/^%[Qq]{(.*)}$/m) 13 | return Puppet::Util::Docs.scrub(match[1]) if match 14 | 15 | Puppet::Util::Docs.scrub(str) 16 | end 17 | 18 | # hacksville, usa 19 | # YARD creates ids in the html with with the style of "label-Module+description", where the markdown 20 | # we use in the README involves the GitHub-style, which is #module-description. This takes our GitHub-style 21 | # links and converts them to reference the YARD-style ids. 22 | # @see https://github.com/octokit/octokit.rb/blob/0f13944e8dbb0210d1e266addd3335c6dc9fe36a/yard/default/layout/html/setup.rb#L5-L14 23 | # @param [String] data HTML document to convert 24 | # @return [String] HTML document with links converted 25 | def self.github_to_yard_links(data) 26 | data.scan(/href="\#(.+)"/).each do |bad_link| 27 | data = data.gsub("=\"##{bad_link.first}\"", "=\"#label-#{bad_link.first.capitalize.tr('-', '+')}\"") 28 | end 29 | 30 | data 31 | end 32 | 33 | # Converts a list of tags into an array of hashes. 34 | # @param [Array] tags List of tags to be converted into an array of hashes. 35 | # @return [Array] Returns an array of tag hashes. 36 | def self.tags_to_hashes(tags) 37 | # Skip over the API tags that are public 38 | tags.select { |t| t.tag_name != 'api' || t.text != 'public' }.map do |t| 39 | next t.to_hash if t.respond_to?(:to_hash) 40 | 41 | tag = { tag_name: t.tag_name } 42 | # grab nested information for @option and @enum tags 43 | if %w[option enum].include?(tag[:tag_name]) 44 | tag[:opt_name] = t.pair.name 45 | tag[:opt_text] = t.pair.text 46 | tag[:opt_types] = t.pair.types if t.pair.types 47 | tag[:parent] = t.name 48 | end 49 | tag[:text] = t.text if t.text 50 | tag[:types] = t.types if t.types 51 | tag[:name] = t.name if t.name 52 | tag 53 | end 54 | end 55 | 56 | # Converts a YARD::Docstring (or String) to a docstring hash for JSON output. 57 | # @param [YARD::Docstring, String] docstring The docstring to convert to a hash. 58 | # @param [Array] select_tags List of tags to select. Other tags will be filtered out. 59 | # @return [Hash] Returns a hash representation of the given docstring. 60 | def self.docstring_to_hash(docstring, select_tags = nil) 61 | hash = {} 62 | hash[:text] = docstring 63 | 64 | if docstring.is_a? YARD::Docstring 65 | tags = tags_to_hashes(docstring.tags.select { |t| select_tags.nil? || select_tags.include?(t.tag_name.to_sym) }) 66 | 67 | unless tags.empty? 68 | hash[:tags] = tags 69 | # .sort_by do |tag| 70 | # sort_key = tag[:tag_name].dup 71 | # sort_key << "-#{tag[:name]}" if tag[:name] 72 | # sort_key << "-#{tag[:opt_name]}" if tag[:opt_name] 73 | # sort_key 74 | # end 75 | end 76 | end 77 | 78 | hash 79 | end 80 | 81 | # Convert Puppet AST to text. 82 | # @param [Puppet::Pops::Model::PopsObject] ast The Puppet AST to convert to text. 83 | # @return [String] Returns a string of Puppet code. 84 | def self.ast_to_text(ast) 85 | ast.locator.extract_tree_text(ast) 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/puppet/application/strings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/application/face_base' 4 | 5 | # Implements the 'puppet strings' application. 6 | class Puppet::Application::Strings < Puppet::Application::FaceBase 7 | end 8 | -------------------------------------------------------------------------------- /lib/puppet/feature/rgen.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/util/feature' 4 | 5 | Puppet.features.add(:rgen, libs: ['rgen/metamodel_builder', 'rgen/ecore/ecore']) 6 | -------------------------------------------------------------------------------- /lib/puppet/feature/yard.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/util/feature' 4 | 5 | Puppet.features.add(:yard, libs: ['yard']) 6 | -------------------------------------------------------------------------------- /puppet-strings.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'puppet-strings/version' 6 | 7 | Gem::Specification.new do |s| 8 | s.name = 'puppet-strings' 9 | s.author = 'Puppet Inc.' 10 | s.version = PuppetStrings::VERSION 11 | s.license = 'Apache-2.0' 12 | s.summary = 'Puppet documentation via YARD' 13 | s.email = 'info@puppet.com' 14 | s.homepage = 'https://github.com/puppetlabs/puppet-strings' 15 | s.required_ruby_version = '>= 3.1.0' 16 | 17 | s.extra_rdoc_files = [ 18 | 'CHANGELOG.md', 19 | 'CONTRIBUTING.md', 20 | 'LICENSE', 21 | 'README.md' 22 | ] 23 | s.files = Dir['CHANGELOG.md', 'README.md', 'LICENSE', 'lib/**/*', 'exe/**/*'] 24 | 25 | s.add_dependency 'puppet', '>= 8.0.0' 26 | s.add_dependency 'rgen', '~> 0.9' 27 | s.add_dependency 'yard', '~> 0.9' 28 | end 29 | -------------------------------------------------------------------------------- /spec/acceptance/generate_json_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'Generating JSON' do 6 | let(:test_module_path) do 7 | sut_module_path(/Module test/) 8 | end 9 | 10 | let(:remote_tmp_path) do 11 | sut_tmp_path 12 | end 13 | 14 | let(:expected) do 15 | { 16 | 'puppet_classes' => [], 17 | 'data_types' => [], 18 | 'data_type_aliases' => [], 19 | 'defined_types' => [], 20 | 'resource_types' => [], 21 | 'providers' => [], 22 | 'puppet_functions' => [ 23 | 'name' => 'function3x', 24 | 'file' => "#{test_module_path}/lib/puppet/parser/functions/function3x.rb", 25 | 'line' => 3, 26 | 'type' => 'ruby3x', 27 | 'signatures' => [ 28 | { 29 | 'signature' => 'function3x()', 30 | 'docstring' => { 31 | 'text' => 'This is the function documentation for `function3x`', 32 | 'tags' => [ 33 | { 34 | 'tag_name' => 'return', 35 | 'text' => '', 36 | 'types' => ['Any'] 37 | } 38 | ] 39 | } 40 | } 41 | ], 42 | 'docstring' => { 43 | 'text' => 'This is the function documentation for `function3x`', 44 | 'tags' => ['tag_name' => 'return', 'text' => '', 'types' => ['Any']] 45 | }, 46 | 'source' => "Puppet::Parser::Functions.newfunction(:function3x, :doc => \"This is the function documentation for `function3x`\") do |args|\nend" 47 | ], 48 | 'puppet_tasks' => [], 49 | 'puppet_plans' => [] 50 | } 51 | end 52 | 53 | it 'renders JSON to stdout when using --format json' do 54 | output = run_shell("puppet strings generate --format json \"#{test_module_path}/lib/puppet/parser/functions/function3x.rb\"").stdout.chomp 55 | expect(JSON.parse(output)).to eq(expected) 56 | end 57 | 58 | it 'writes JSON to a file when using --format json --out' do 59 | tmpfile = File.join(remote_tmp_path, 'json_output.json') 60 | run_shell("puppet strings generate --format json --out #{tmpfile} \"#{test_module_path}/lib/puppet/parser/functions/function3x.rb\"") 61 | expect(JSON.parse(file(tmpfile).content)).to eq(expected) 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /spec/acceptance/generate_markdown_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'Generating Markdown' do 6 | let(:test_module_path) do 7 | sut_module_path(/Module test/) 8 | end 9 | 10 | let(:remote_tmp_path) do 11 | sut_tmp_path 12 | end 13 | 14 | expected = <<~EOF 15 | # Reference 16 | 17 | ## Classes 18 | * [`test`](#test): This class exists to serve as fixture data for testing the puppet strings face 19 | 20 | ## Classes 21 | 22 | ### test 23 | 24 | #### Examples 25 | ```puppet 26 | class { "test": } 27 | ``` 28 | 29 | #### Parameters 30 | 31 | ##### `package_name` 32 | 33 | The name of the package 34 | 35 | ##### `service_name` 36 | 37 | The name of the service 38 | 39 | EOF 40 | 41 | it 'renders Markdown to stdout when using --format markdown' do 42 | skip('This test is broken. Does not output to STDOUT by default.') 43 | output = PuppetLitmus::PuppetHelpers.run_shell("puppet strings generate --format markdown \"#{test_module_path}/manifests/init.pp\"").stdout.chomp 44 | expect(output).to eq(expected) 45 | end 46 | 47 | it 'writes Markdown to a file when using --format markdown and --out' do 48 | tmpfile = File.join(remote_tmp_path, 'md_output.md') 49 | PuppetLitmus::PuppetHelpers.run_shell("puppet strings generate --format markdown --out \"#{tmpfile}\" \"#{test_module_path}/manifests/init.pp\"") 50 | expect(file(tmpfile)).to contain expected 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/acceptance/running_strings_generate_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | include PuppetLitmus 5 | 6 | describe 'Generating module documentation using generate action' do 7 | let(:sut_work_dir) do 8 | PuppetLitmus::PuppetHelpers.run_shell('pwd').stdout.chomp 9 | end 10 | 11 | before :all do 12 | # TODO: Linux only 13 | test_module_path = sut_module_path(/Module test/) 14 | PuppetLitmus::PuppetHelpers.run_shell("puppet strings generate \"#{test_module_path}/**/*.{rb,pp}\"") 15 | end 16 | 17 | def expect_file_contain(path, expected_contents) 18 | file_path = File.join(sut_work_dir, path) 19 | file_content = file(file_path).content 20 | expected_contents.each do |expected| 21 | expect(file_content).to include(expected) 22 | end 23 | end 24 | 25 | it 'generates documentation for manifests' do 26 | expect_file_contain('doc/puppet_classes/test.html', ['Class: test']) 27 | end 28 | 29 | it 'generates documentation for puppet functions' do 30 | skip('This test is failing. Appear to be legitimate failures.') 31 | expect_file_contain('doc/puppet_functions_puppet/test_3A_3Aadd.html', [ 32 | 'Adds two integers together.', 33 | # These tests are failing. Appear to be legitimate failures. 34 | '

    The first integer to add.

    ', 35 | '

    The second integer to add.

    ', 36 | '

    Returns the sum of x and y.

    ' 37 | ]) 38 | end 39 | 40 | it 'generates documentation for 3x functions' do 41 | expect_file_contain('doc/puppet_functions_ruby3x/function3x.html', ['This is the function documentation for function3x']) 42 | end 43 | 44 | it 'generates documentation for 4x functions' do 45 | expect_file_contain('doc/puppet_functions_ruby4x/function4x.html', ['This is a function which is used to test puppet strings']) 46 | end 47 | 48 | it 'generates documentation for custom types' do 49 | expect_file_contain('doc/puppet_types/database.html', [ 50 | '

    An example server resource type.

    ', 51 | '

    The database file to use.

    ', 52 | '

    Documentation for a dynamic property.

    ', 53 | '

    The database server name.

    ', 54 | '

    Documentation for a dynamic parameter.

    ', 55 | '

    The provider supports encryption.

    ' 56 | ]) 57 | end 58 | 59 | it 'generates documentation for custom providers' do 60 | expect_file_contain('doc/puppet_providers_database/linux.html', [ 61 | 'The database provider on Linux', 62 | 'osfamily — linux', 63 | 'database — /usr/bin/database' 64 | ]) 65 | end 66 | 67 | it 'generates documentation for puppet data types' do 68 | expect_file_contain('doc/puppet_data_types/AcceptanceDataType.html', [ 69 | 'A variant parameter called param1', 70 | 'Optional String parameter called param2', 71 | '

    func1

    ', 72 | '

    func1 documentation

    ', 73 | '

    param1 func1 documentation

    ', 74 | '

    param2 func1 documentation

    ' 75 | ]) 76 | end 77 | 78 | it 'generates documentation for puppet data type aliases' do 79 | expect_file_contain('doc/puppet_data_type_aliases/Test_3A_3AElephant.html', [ 80 | 'Data Type: Test::Elephant', 81 | 'types/elephant.pp', 82 | 'A simple elephant type.' 83 | ]) 84 | end 85 | 86 | it 'generates documentation for enum tag' do 87 | expect_file_contain('doc/puppet_classes/test.html', [ 88 | '

    Enum Options (myenum):

    ', 89 | 'a', 90 | "—

    Option A

    \n
    ", 91 | 'b', 92 | "—

    Option B

    \n
    " 93 | ]) 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/functions/add.pp: -------------------------------------------------------------------------------- 1 | # Adds two integers together. 2 | # @param x The first integer to add. 3 | # @param y The second integer to add. 4 | # @return [Integer] Returns the sum of x and y. 5 | # @example Example of adding two integers. 6 | # test::add(1, 2) => 3 7 | function test::add(Integer $x, Integer $y) { 8 | $x + $y 9 | } 10 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/lib/puppet/datatypes/acceptancedatatype.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # An example Acceptance Puppet Data Type in Ruby. 4 | # 5 | # @param param1 A variant parameter called param1. 6 | # @param param2 Optional String parameter called param2. 7 | # @method func1(param1, param2) 8 | # func1 documentation 9 | # @param [String] param1 param1 func1 documentation 10 | # @param [Integer] param2 param2 func1 documentation 11 | # @return [Optional[String]] 12 | Puppet::DataTypes.create_type('AcceptanceDataType') do 13 | interface <<~'PUPPET' 14 | attributes => { 15 | param1 => Variant[Numeric, String[1,2]], 16 | param2 => { type => Optional[String[1]], value => "param2" } 17 | }, 18 | functions => { 19 | func1 => Callable[[String, Integer], Optional[String]] 20 | } 21 | PUPPET 22 | end 23 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/lib/puppet/functions/4x_function.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # function 4x 4 | # 5 | # This is a function which is used to test puppet strings 6 | Puppet::Functions.create_function(:function4x) do 7 | end 8 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/lib/puppet/parser/functions/function3x.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Parser::Functions.newfunction(:function3x, :doc => "This is the function documentation for `function3x`") do |args| 4 | end 5 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/lib/puppet/provider/server/linux.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.type(:database).provide :linux do 4 | confine 'osfamily' => 'linux' 5 | defaultfor 'osfamily' => 'linux' 6 | commands :database => '/usr/bin/database' 7 | 8 | desc 'The database provider on Linux.' 9 | 10 | # ... 11 | end 12 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/lib/puppet/type/database.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # @!puppet.type.param [value1, value2, value3] my_param Documentation for a dynamic parameter. 4 | # @!puppet.type.property [foo, bar, baz] my_prop Documentation for a dynamic property. 5 | Puppet::Type.newtype(:database) do 6 | desc 'An example server resource type.' 7 | feature :encryption, 'The provider supports encryption.', methods: [:encrypt] 8 | 9 | newparam(:address) do 10 | isnamevar 11 | desc 'The database server name.' 12 | end 13 | 14 | newproperty(:file) do 15 | desc 'The database file to use.' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # Class: test 2 | # 3 | # This class exists to serve as fixture data for testing the puppet strings face 4 | # 5 | # @example 6 | # class { "test": } 7 | # 8 | # @param package_name The name of the package 9 | # @param service_name The name of the service 10 | # @param myenum 11 | # @enum myenum a Option A 12 | # @enum myenum b Option B 13 | class test ( 14 | $package_name = $test::params::package_name, 15 | $service_name = $test::params::service_name, 16 | Enum['a', 'b'] $myenum = 'a', 17 | 18 | ) inherits test::params { 19 | 20 | # validate parameters here 21 | 22 | class { 'test::install': } -> 23 | class { 'test::config': } ~> 24 | class { 'test::service': } -> 25 | Class['test'] 26 | 27 | File { 28 | owner => 'user', 29 | path => 'some/file/path', 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/manifests/triple_nested_classes.pp: -------------------------------------------------------------------------------- 1 | # Testing tested classes 2 | # docs stuff 3 | # @param nameservers [String] Don't ask me what this does! 4 | # @param default_lease_time [Integer[1024, 8192]] text goes here 5 | # @param max_lease_time does stuff 6 | class outer ( 7 | $dnsdomain, 8 | $nameservers, 9 | $default_lease_time = 3600, 10 | $max_lease_time = 86400 11 | ) { 12 | # @param options [String[5,7]] gives user choices 13 | # @param multicast [Boolean] foobar 14 | # @param servers yep, that's right 15 | class middle ( 16 | $options = "iburst", 17 | $servers, 18 | $multicast = false 19 | ) { 20 | class inner ( 21 | $choices = "uburst", 22 | $secenekler = "weallburst", 23 | $boxen, 24 | $manyspell = true 25 | ) {} 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "username-test", 3 | "version": "0.0.1", 4 | "author": "username", 5 | "summary": "brief summary", 6 | "license": "MIT", 7 | "source": "git://github.com/not_a/real_repo.git", 8 | "dependencies": [ 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /spec/fixtures/acceptance/modules/test/types/elephant.pp: -------------------------------------------------------------------------------- 1 | # A simple elephant type. 2 | type Test::Elephant = String[2] 3 | -------------------------------------------------------------------------------- /spec/fixtures/json/backup.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Allows you to backup your database to local file.", 3 | "input_method": "stdin", 4 | "parameters": { 5 | "database": { 6 | "description": "Database to connect to", 7 | "type": "Optional[String[1]]" 8 | }, 9 | "user": { 10 | "description": "The user", 11 | "type": "Optional[String[1]]" 12 | }, 13 | "password": { 14 | "description": "The password", 15 | "type": "Optional[String[1]]" 16 | }, 17 | "sql": { 18 | "description": "Path to file you want backup to", 19 | "type": "String[1]" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spec/fixtures/plans/plan.pp: -------------------------------------------------------------------------------- 1 | # A simple plan. 2 | # @param param1 First param. 3 | # @param param2 Second param. 4 | # @param param3 Third param. 5 | plan plann(String $param1, $param2, Integer $param3 = 1) { 6 | } 7 | -------------------------------------------------------------------------------- /spec/fixtures/puppet/class.pp: -------------------------------------------------------------------------------- 1 | # An overview for a simple class. 2 | # @summary A simple class. 3 | # @todo Do a thing 4 | # @deprecated No longer supported and will be removed in a future release 5 | # @note some note 6 | # @since 1.0.0 7 | # @see www.puppet.com 8 | # @example This is an example 9 | # class { 'klass': 10 | # param1 => 1, 11 | # param3 => 'foo', 12 | # } 13 | # @example This is another example 14 | # class { 'klass': 15 | # param1 => 1, 16 | # param3 => 'foo', 17 | # } 18 | # @raise SomeError 19 | # @param param1 First param. 20 | # @param param2 Second param. 21 | # @option param2 [String] :opt1 something about opt1 22 | # @option param2 [Hash] :opt2 a hash of stuff 23 | # @param param3 Third param. 24 | # @param param4 Fourth param. 25 | # @enum param4 :one One option 26 | # @enum param4 :two Second option 27 | # 28 | class klass ( 29 | Integer $param1 = 1, 30 | $param2 = undef, 31 | String $param3 = 'hi', 32 | Enum['one', 'two'] $param4 = 'two', 33 | ) inherits foo::bar { 34 | } 35 | 36 | # Overview for class noparams 37 | # @api private 38 | class noparams () {} 39 | 40 | # An overview for a simple defined type. 41 | # @summary A simple defined type. 42 | # @since 1.1.0 43 | # @see www.puppet.com 44 | # @example Here's an example of this type: 45 | # klass::dt { 'foo': 46 | # param1 => 33, 47 | # param4 => false, 48 | # } 49 | # @return shouldn't return squat 50 | # @raise SomeError 51 | # @param param1 First param. 52 | # @param param2 Second param. 53 | # @option param2 [String] :opt1 something about opt1 54 | # @option param2 [Hash] :opt2 a hash of stuff 55 | # @param param3 Third param. 56 | # @param param4 Fourth param. 57 | # @param param5 Fifth param. 58 | # @enum param5 :a Option A 59 | # @enum param5 :b Option B 60 | define klass::dt ( 61 | Integer $param1 = 44, 62 | $param2, 63 | String $param3 = 'hi', 64 | Boolean $param4 = true, 65 | Enum['a', 'b'] $param5 = 'a' 66 | ) { 67 | } 68 | -------------------------------------------------------------------------------- /spec/fixtures/puppet/function.pp: -------------------------------------------------------------------------------- 1 | # A simple Puppet function. 2 | # @param param1 First param. 3 | # @param param2 Second param. 4 | # @param param3 Third param. 5 | # @option param3 [Array] :param3opt Something about this option 6 | # @param param4 Fourth param. 7 | # @enum param4 :yes Yes option. 8 | # @enum param4 :no No option. 9 | # @raise SomeError this is some error 10 | # @return [Undef] Returns nothing. 11 | # @example Test 12 | # $result = func(1, 2) 13 | function func(Integer $param1, $param2, String $param3 = hi, Enum['yes', 'no'] $param4 = 'yes') { 14 | } 15 | -------------------------------------------------------------------------------- /spec/fixtures/puppet/type_alias.pp: -------------------------------------------------------------------------------- 1 | # Documentation for Amodule::SimpleAlias 2 | type Amodule::SimpleAlias = Variant[Numeric,String[1,20]] 3 | 4 | # Documentation for Amodule::ComplexAlias 5 | type Amodule::ComplexAlias = Struct[{ 6 | value_type => Optional[ValueType], 7 | merge => Optional[MergeType] 8 | }] 9 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/data_type.rb: -------------------------------------------------------------------------------- 1 | # An example Puppet Data Type in Ruby. 2 | # 3 | # @param param1 A variant parameter. 4 | # @param param2 Optional String parameter. 5 | # @!method func1(param1, param2) 6 | # func1 documentation 7 | # @param [String] param1 param1 documentation 8 | # @param [Integer] param2 param2 documentation 9 | # @return [Optional[String]] 10 | Puppet::DataTypes.create_type('UnitDataType') do 11 | interface <<~'PUPPET' 12 | attributes => { 13 | param1 => Variant[Numeric, String[1,2]], 14 | param2 => { type => Optional[String[1]], value => "param2" } 15 | }, 16 | functions => { 17 | func1 => Callable[[String, Integer], Optional[String]] 18 | } 19 | PUPPET 20 | end 21 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/func3x.rb: -------------------------------------------------------------------------------- 1 | # An example 3.x function 2 | Puppet::Parser::Functions.newfunction(:func3x, doc: <<~'DOC') do |*args| 3 | Documentation for an example 3.x function. 4 | @param param1 [String] The first parameter. 5 | @param param2 [Integer] The second parameter. 6 | @return [Undef] 7 | @example Calling the function. 8 | func3x('hi', 10) 9 | DOC 10 | # ... 11 | end 12 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/func4x.rb: -------------------------------------------------------------------------------- 1 | # An example 4.x function. 2 | # 3 | # @example Calling the function 4 | # $result = func4x(1, 'foo') 5 | # 6 | # @example Calling the function with all args 7 | # $result = func4x(1, 'foo', ['bar']) 8 | Puppet::Functions.create_function(:func4x) do 9 | # An overview for the first overload. 10 | # @raise SomeError this is some error 11 | # @param param1 The first parameter. 12 | # @param param2 The second parameter. 13 | # @option param2 [String] :option an option 14 | # @option param2 [String] :option2 another option 15 | # @param param3 The third parameter. 16 | # @param param4 The fourth parameter. 17 | # @enum param4 :one Option one. 18 | # @enum param4 :two Option two. 19 | # @return Returns nothing. 20 | # @example Calling the function foo 21 | # $result = func4x(1, 'foooo') 22 | # 23 | dispatch :foo do 24 | param 'Integer', :param1 25 | param 'Any', :param2 26 | optional_param 'Array[String]', :param3 27 | optional_param 'Enum[one, two]', :param4 28 | return_type 'Undef' 29 | end 30 | 31 | # An overview for the second overload. 32 | # @param param The first parameter. 33 | # @param block The block parameter. 34 | # @return Returns a string. 35 | # @example Calling the function bar 36 | # $result = func4x(1, 'bar', ['foo']) 37 | dispatch :other do 38 | param 'Boolean', :param 39 | block_param 40 | return_type 'String' 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/func4x_1.rb: -------------------------------------------------------------------------------- 1 | # An example 4.x function with only one signature. 2 | Puppet::Functions.create_function(:func4x_1) do 3 | # @param param1 The first parameter. 4 | # @return [Undef] Returns nothing. 5 | dispatch :foobarbaz do 6 | param 'Integer', :param1 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/provider.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.type(:database).provide :linux do 2 | desc 'An example provider on Linux.' 3 | confine kernel: 'Linux' 4 | confine osfamily: 'RedHat' 5 | defaultfor :kernel => 'Linux' 6 | defaultfor :osfamily => 'RedHat', :operatingsystemmajrelease => '7' 7 | has_feature :implements_some_feature 8 | has_feature :some_other_feature 9 | commands foo: '/usr/bin/foo' 10 | end 11 | 12 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/resource_api.rb: -------------------------------------------------------------------------------- 1 | Puppet::ResourceApi.register_type( 2 | name: 'apt_key', 3 | docs: <<~'EOS', 4 | @summary Example resource type using the new API. 5 | @raise SomeError 6 | This type provides Puppet with the capabilities to manage GPG keys needed 7 | by apt to perform package validation. Apt has it's own GPG keyring that can 8 | be manipulated through the `apt-key` command. 9 | @example here's an example 10 | apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F': 11 | source => 'http://apt.puppetlabs.com/pubkey.gpg' 12 | } 13 | 14 | **Autorequires**: 15 | If Puppet is given the location of a key file which looks like an absolute 16 | path this type will autorequire that file. 17 | EOS 18 | attributes: { 19 | ensure: { 20 | type: 'Enum[present, absent]', 21 | desc: 'Whether this apt key should be present or absent on the target system.' 22 | }, 23 | id: { 24 | type: 'Variant[Pattern[/\A(0x)?[0-9a-fA-F]{8}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{16}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{40}\Z/]]', 25 | behaviour: :namevar, 26 | desc: 'The ID of the key you want to manage.', 27 | }, 28 | # ... 29 | created: { 30 | type: 'String', 31 | behaviour: :read_only, 32 | desc: 'Date the key was created, in ISO format.', 33 | }, 34 | }, 35 | autorequires: { 36 | file: '$source', # will evaluate to the value of the `source` attribute 37 | package: 'apt', 38 | }, 39 | ) 40 | -------------------------------------------------------------------------------- /spec/fixtures/ruby/resource_type.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:database) do 2 | desc <<~'DESC' 3 | An example database server type. 4 | @option opts :foo bar 5 | @enum ensure :up Upstate 6 | @enum ensure :down Downstate 7 | @raise SomeError 8 | @example here's an example 9 | database { 'foo': 10 | address => 'qux.baz.bar', 11 | } 12 | DESC 13 | feature :encryption, 'The provider supports encryption.', methods: [:encrypt] 14 | ensurable do 15 | desc 'What state the database should be in.' 16 | defaultvalues 17 | aliasvalue(:up, :present) 18 | aliasvalue(:down, :absent) 19 | defaultto :up 20 | end 21 | 22 | newparam(:address) do 23 | isnamevar 24 | desc 'The database server name.' 25 | end 26 | 27 | newparam(:encryption_key, required_features: :encryption) do 28 | desc 'The encryption key to use.' 29 | end 30 | 31 | newparam(:encrypt, :parent => Puppet::Parameter::Boolean) do 32 | desc 'Whether or not to encrypt the database.' 33 | defaultto false 34 | end 35 | 36 | newproperty(:file) do 37 | desc 'The database file to use.' 38 | end 39 | 40 | newproperty(:log_level) do 41 | desc 'The log level to use.' 42 | newvalue(:debug) 43 | newvalue(:warn) 44 | newvalue(:error) 45 | defaultto 'warn' 46 | end 47 | 48 | newcheck(:exists) do 49 | desc 'Check to see if the database already exists' 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/markdownlint_style.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | all 4 | 5 | # Update line length to 120 chars. 6 | rule 'MD013', line_length: 120 7 | 8 | # Allow duplicate headings. 9 | exclude_rule 'MD024' 10 | 11 | # Allow trailing punctuation in headings. 12 | exclude_rule 'MD026' 13 | 14 | # Allow html tags 15 | exclude_rule 'MD033' 16 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if ENV['COVERAGE'] == 'yes' 4 | require 'simplecov' 5 | require 'simplecov-console' 6 | 7 | SimpleCov.formatters = [ 8 | SimpleCov::Formatter::HTMLFormatter, 9 | SimpleCov::Formatter::Console 10 | ] 11 | 12 | SimpleCov.start do 13 | track_files 'lib/**/*.rb' 14 | add_filter 'lib/puppet-strings/version.rb' 15 | add_filter '/spec' 16 | end 17 | end 18 | 19 | require 'mocha' 20 | require 'mdl' 21 | require 'rspec' 22 | require 'json_spec' 23 | require 'puppet/version' 24 | require 'puppet-strings' 25 | require 'puppet-strings/markdown' 26 | require 'puppet-strings/markdown/base' 27 | require 'puppet-strings/yard' 28 | 29 | # Explicitly set up YARD once 30 | PuppetStrings::Yard.setup! 31 | 32 | # Enable testing of Puppet functions if running against 4.1+ 33 | TEST_PUPPET_FUNCTIONS = Puppet::Util::Package.versioncmp(Puppet.version, '4.1.0') >= 0 34 | 35 | # Enable testing of Puppet language functions declared with return type if running against 4.8+ 36 | TEST_FUNCTION_RETURN_TYPE = Puppet::Util::Package.versioncmp(Puppet.version, '4.8.0') >= 0 37 | 38 | # Enable testing of Plans if Puppet version is greater than 5.0.0 39 | TEST_PUPPET_PLANS = Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') >= 0 40 | 41 | # Enable testing of Data Types if Puppet version is greater than 4.1.0 42 | TEST_PUPPET_DATATYPES = Puppet::Util::Package.versioncmp(Puppet.version, '4.1.0') >= 0 43 | 44 | RSpec.configure do |config| 45 | config.mock_with :mocha 46 | 47 | config.before do 48 | # Always clear the YARD registry before each example 49 | YARD::Registry.clear 50 | end 51 | end 52 | 53 | def lint_markdown(content) 54 | # Load default mdl ruleset 55 | ruleset = MarkdownLint::RuleSet.new.tap(&:load_default) 56 | 57 | # Apply custom style to ruleset rules 58 | MarkdownLint::Style.load(File.join(__dir__, 'markdownlint_style.rb'), ruleset.rules) 59 | 60 | # Create a document 61 | doc = MarkdownLint::Doc.new(content, false) 62 | 63 | # Run the rules 64 | violations = [] 65 | ruleset.rules.each do |id, rule| 66 | error_lines = rule.check.call(doc) 67 | next if error_lines.nil? || error_lines.empty? 68 | 69 | # record the error 70 | error_lines.each do |line| 71 | line += doc.offset # Correct line numbers for any yaml front matter 72 | violations << "#{line}: #{id} #{rule.description}: #{doc.lines[line - 1]}" 73 | end 74 | end 75 | violations 76 | end 77 | 78 | RSpec::Matchers.define :have_no_markdown_lint_errors do 79 | match do |actual| 80 | @violations = lint_markdown(actual) 81 | @violations.empty? 82 | end 83 | 84 | failure_message do |actual| 85 | "expected that #{actual.length > 80 ? "#{actual.slice(0, 80).inspect}..." : actual.inspect} would have no markdown lint errors but got #{@violations.join("\n")}" 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet_litmus' 4 | require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_acceptance_local.rb')) 5 | 6 | PuppetLitmus.configure! 7 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance_local.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def sut_module_path(module_regex) 4 | modules = JSON.parse(run_shell('bundle exec puppet module list --modulepath spec/fixtures/modules --render-as json').stdout) 5 | test_module_info = modules['modules_by_path'].values.flatten.find { |mod_info| mod_info =~ module_regex } 6 | test_module_info.match(/\(([^)]*)\)/)[1] 7 | end 8 | 9 | def sut_tmp_path 10 | # TODO: Linux only 11 | '/tmp/' 12 | end 13 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/code_objects/task_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'puppet-strings/yard/code_objects/task' 5 | require 'puppet-strings/yard/parsers/json/task_statement' 6 | 7 | describe PuppetStrings::Yard::CodeObjects::Task do 8 | subject(:spec_subject) { described_class.new(statement) } 9 | 10 | let(:source) { <<~SOURCE } 11 | { 12 | "description": "Allows you to backup your database to local file.", 13 | "input_method": "stdin", 14 | "parameters": { 15 | "database": { 16 | "description": "Database to connect to", 17 | "type": "Optional[String[1]]" 18 | }, 19 | "user": { 20 | "description": "The user", 21 | "type": "Optional[String[1]]" 22 | }, 23 | "password": { 24 | "description": "The password", 25 | "type": "Optional[String[1]]" 26 | }, 27 | "sql": { 28 | "description": "Path to file you want backup to", 29 | "type": "String[1]" 30 | } 31 | } 32 | } 33 | SOURCE 34 | let(:json) { JSON.parse(source) } 35 | let(:statement) { PuppetStrings::Yard::Parsers::JSON::TaskStatement.new(json, source, 'test.json') } 36 | 37 | describe '#type' do 38 | it 'returns the correct type' do 39 | expect(spec_subject.type).to eq(:puppet_task) 40 | end 41 | end 42 | 43 | describe '#source' do 44 | it 'returns the source' do 45 | expect(spec_subject.source).to eq(source) 46 | end 47 | end 48 | 49 | describe '#to_hash' do 50 | let(:expected) do 51 | { 52 | name: 'test', 53 | supports_noop: false, 54 | docstring: { 55 | text: 'Allows you to backup your database to local file.', 56 | tags: [ 57 | { 58 | name: 'database', 59 | tag_name: 'param', 60 | text: 'Database to connect to', 61 | types: ['Optional[String[1]]'] 62 | }, 63 | { 64 | name: 'user', 65 | tag_name: 'param', 66 | text: 'The user', 67 | types: ['Optional[String[1]]'] 68 | }, 69 | { 70 | name: 'password', 71 | tag_name: 'param', 72 | text: 'The password', 73 | types: ['Optional[String[1]]'] 74 | }, 75 | { 76 | name: 'sql', 77 | tag_name: 'param', 78 | text: 'Path to file you want backup to', 79 | types: ['String[1]'] 80 | } 81 | ] 82 | }, 83 | file: 'test.json', 84 | input_method: 'stdin', 85 | line: 0, 86 | source: "{\n \"description\": \"Allows you to backup your database to local file.\",\n \"input_method\": \"stdin\",\n \"parameters\": {\n \"database\": {\n \"description\": \"Database to connect to\",\n \"type\": \"Optional[String[1]]\"\n },\n \"user\": {\n \"description\": \"The user\",\n \"type\": \"Optional[String[1]]\"\n },\n \"password\": {\n \"description\": \"The password\",\n \"type\": \"Optional[String[1]]\"\n },\n \"sql\": {\n \"description\": \"Path to file you want backup to\",\n \"type\": \"String[1]\"\n }\n }\n}\n" # rubocop:disable Layout/LineLength 87 | } 88 | end 89 | 90 | it 'returns the correct hash' do 91 | expect(spec_subject.to_hash).to eq(expected) 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/handlers/json/task_handler_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'puppet-strings/yard' 5 | 6 | describe PuppetStrings::Yard::Handlers::JSON::TaskHandler do 7 | subject(:spec_subject) do 8 | YARD::Parser::SourceParser.parse_string(source, :json) 9 | YARD::Registry.all(:puppet_task) 10 | end 11 | 12 | describe 'parsing task metadata with a syntax error' do 13 | let(:source) { <<~SOURCE } 14 | { 15 | "input_method": "stdin", 16 | "parameters": 17 | "database": { 18 | "description": "Database to connect to", 19 | "type": "Optional[String[1]]" 20 | } 21 | } 22 | } 23 | SOURCE 24 | 25 | it 'logs an error' do 26 | expect { spec_subject }.to output(/\[error\]: Failed to parse \(stdin\):/).to_stdout_from_any_process 27 | expect(spec_subject.empty?).to be(true) 28 | end 29 | end 30 | 31 | describe 'parsing task metadata with a missing description' do 32 | let(:source) { <<~SOURCE } 33 | { 34 | "input_method": "stdin", 35 | "parameters": { 36 | "database": { 37 | "description": "Database to connect to", 38 | "type": "Optional[String[1]]" 39 | }, 40 | "user": { 41 | "description": "The user", 42 | "type": "Optional[String[1]]" 43 | }, 44 | "password": { 45 | "description": "The password", 46 | "type": "Optional[String[1]]" 47 | }, 48 | "sql": { 49 | "description": "Path to file you want backup to", 50 | "type": "String[1]" 51 | } 52 | } 53 | } 54 | SOURCE 55 | 56 | it 'logs a warning' do 57 | expect { spec_subject }.to output(/\[warn\]: Missing a description for Puppet Task \(stdin\)/).to_stdout_from_any_process 58 | end 59 | end 60 | 61 | describe 'parsing task metadata with a description' do 62 | let(:source) { <<~SOURCE } 63 | { 64 | "description": "Allows you to backup your database to local file.", 65 | "input_method": "stdin", 66 | "parameters": { 67 | "database": { 68 | "description": "Database to connect to", 69 | "type": "Optional[String[1]]" 70 | }, 71 | "user": { 72 | "description": "The user", 73 | "type": "Optional[String[1]]" 74 | }, 75 | "password": { 76 | "description": "The password", 77 | "type": "Optional[String[1]]" 78 | }, 79 | "sql": { 80 | "description": "Path to file you want backup to", 81 | "type": "String[1]" 82 | } 83 | } 84 | } 85 | 86 | SOURCE 87 | 88 | it 'registers a task object' do 89 | expect(spec_subject.size).to eq(1) 90 | object = spec_subject.first 91 | expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Task) 92 | expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Tasks.instance) 93 | end 94 | end 95 | 96 | describe 'parsing task metadata with a missing parameter description' do 97 | let(:source) { <<~SOURCE } 98 | { 99 | "description": "Allows you to backup your database to local file.", 100 | "input_method": "stdin", 101 | "parameters": { 102 | "database": { 103 | "type": "Optional[String[1]]" 104 | } 105 | } 106 | } 107 | SOURCE 108 | 109 | it 'outputs a warning' do 110 | expect { spec_subject }.to output(/\[warn\]: Missing description for param 'database' in Puppet Task \(stdin\)/).to_stdout_from_any_process 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/handlers/puppet/data_type_alias_handler_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'puppet-strings/yard' 5 | 6 | describe PuppetStrings::Yard::Handlers::Puppet::DataTypeAliasHandler, if: TEST_PUPPET_DATATYPES do 7 | subject(:spec_subject) do 8 | YARD::Parser::SourceParser.parse_string(source, :puppet) 9 | YARD::Registry.all(:puppet_data_type_alias) 10 | end 11 | 12 | describe 'parsing source without a type alias definition' do 13 | let(:source) { 'notice hi' } 14 | 15 | it 'no aliases should be in the registry' do 16 | expect(spec_subject.empty?).to be(true) 17 | end 18 | end 19 | 20 | describe 'parsing source with a syntax error' do 21 | let(:source) { 'type Testype =' } 22 | 23 | it 'logs an error' do 24 | expect { spec_subject }.to output(/\[error\]: Failed to parse \(stdin\): Syntax error at end of (file|input)/).to_stdout_from_any_process 25 | expect(spec_subject.empty?).to be(true) 26 | end 27 | end 28 | 29 | describe 'parsing a data type alias with a missing docstring' do 30 | let(:source) { 'type Testype = String[1]' } 31 | 32 | it 'logs a warning' do 33 | expect { spec_subject }.to output(/\[warn\]: Missing documentation for Puppet type alias 'Testype' at \(stdin\):1\./).to_stdout_from_any_process 34 | end 35 | end 36 | 37 | describe 'parsing a data type alias with a summary' do 38 | context 'when the summary has fewer than 140 characters' do 39 | let(:source) { <<~SOURCE } 40 | # A simple foo type. 41 | # @summary A short summary. 42 | type Testype = String[1] 43 | SOURCE 44 | 45 | it 'parses the summary' do 46 | expect { spec_subject }.not_to output.to_stdout_from_any_process 47 | expect(spec_subject.size).to eq(1) 48 | summary = spec_subject.first.tags(:summary) 49 | expect(summary.first.text).to eq('A short summary.') 50 | end 51 | end 52 | 53 | context 'when the summary has more than 140 characters' do 54 | let(:source) { <<~SOURCE } 55 | # A simple foo type. 56 | # @summary A short summary that is WAY TOO LONG. AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH this is not what a summary is for! It should be fewer than 140 characters!! 57 | type Testype = String[1] 58 | SOURCE 59 | 60 | it 'logs a warning' do 61 | expect { spec_subject }.to output(/\[warn\]: The length of the summary for puppet_data_type_alias 'Testype' exceeds the recommended limit of 140 characters./).to_stdout_from_any_process 62 | end 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/handlers/ruby/type_extras_handler_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'puppet-strings/yard' 5 | 6 | describe PuppetStrings::Yard::Handlers::Ruby::TypeExtrasHandler do 7 | subject(:spec_subject) do 8 | YARD::Parser::SourceParser.parse_string(source, :ruby) 9 | YARD::Registry.all(:puppet_type) 10 | end 11 | 12 | describe 'parsing source with newproperty' do 13 | let(:source) { <<~SOURCE } 14 | Puppet::Type.newtype(:database) do 15 | desc 'database' 16 | end 17 | Puppet::Type.type(:database).newproperty(:file) do 18 | desc 'The database file to use.' 19 | end 20 | SOURCE 21 | 22 | it 'generates a doc string for a property' do 23 | expect(spec_subject.size).to eq(1) 24 | object = spec_subject.first 25 | expect(object.properties.size).to eq(1) 26 | expect(object.properties[0].name).to eq('file') 27 | expect(object.properties[0].docstring).to eq('The database file to use.') 28 | end 29 | end 30 | 31 | describe 'parsing source with newparam' do 32 | let(:source) { <<~SOURCE } 33 | Puppet::Type.newtype(:database) do 34 | desc 'database' 35 | end 36 | Puppet::Type.type(:database).newparam(:name) do 37 | desc 'The database server name.' 38 | end 39 | SOURCE 40 | 41 | it 'generates a doc string for a parameter that is also a namevar' do 42 | expect(spec_subject.size).to eq(1) 43 | object = spec_subject.first 44 | expect(object.parameters.size).to eq(1) 45 | expect(object.parameters[0].name).to eq('name') 46 | expect(object.parameters[0].docstring).to eq('The database server name.') 47 | expect(object.parameters[0].isnamevar).to be(true) 48 | end 49 | end 50 | 51 | describe 'parsing source with ensurable' do 52 | let(:source) { <<~SOURCE } 53 | Puppet::Type.newtype(:database) do 54 | desc 'database' 55 | end 56 | Puppet::Type.type(:database).ensurable do 57 | desc 'What state the database should be in.' 58 | end 59 | SOURCE 60 | 61 | it 'generates a doc string for an ensurable' do 62 | expect(spec_subject.size).to eq(1) 63 | object = spec_subject.first 64 | expect(object.properties.size).to eq(1) 65 | expect(object.properties[0].name).to eq('ensure') 66 | expect(object.properties[0].docstring).to eq('What state the database should be in.') 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/parsers/json/parser_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'puppet-strings/yard' 5 | 6 | describe PuppetStrings::Yard::Parsers::JSON::Parser do 7 | subject(:spec_subject) { described_class.new(source, file) } 8 | 9 | let(:file) { 'test.json' } 10 | 11 | describe 'initialization of the parser' do 12 | let(:source) { '{}' } 13 | 14 | it 'stores the original source' do 15 | expect(spec_subject.source).to eq(source) 16 | end 17 | 18 | it 'stores the original file name' do 19 | expect(spec_subject.file).to eq(file) 20 | end 21 | 22 | it 'has no relevant statements' do 23 | spec_subject.parse 24 | 25 | expect(spec_subject.enumerator).to be_empty 26 | end 27 | end 28 | 29 | describe 'parsing invalid JSON' do 30 | let(:source) { <<~SOURCE } 31 | class foo { 32 | SOURCE 33 | 34 | it 'raises an exception' do 35 | expect { spec_subject.parse }.to output(/\[error\]: Failed to parse test.json/).to_stdout_from_any_process 36 | end 37 | end 38 | 39 | describe 'parsing valid task metadata JSON' do 40 | let(:source) { <<~SOURCE } 41 | { 42 | "description": "Allows you to backup your database to local file.", 43 | "input_method": "stdin", 44 | "parameters": { 45 | "database": { 46 | "description": "Database to connect to", 47 | "type": "Optional[String[1]]" 48 | }, 49 | "user": { 50 | "description": "The user", 51 | "type": "Optional[String[1]]" 52 | }, 53 | "password": { 54 | "description": "The password", 55 | "type": "Optional[String[1]]" 56 | }, 57 | "sql": { 58 | "description": "Path to file you want backup to", 59 | "type": "String[1]" 60 | } 61 | } 62 | } 63 | SOURCE 64 | 65 | it 'parses the JSON and extract a TaskStatement' do 66 | spec_subject.parse 67 | 68 | expect(spec_subject.enumerator.size).to eq(1) 69 | statement = spec_subject.enumerator.first 70 | expect(statement).to be_instance_of(PuppetStrings::Yard::Parsers::JSON::TaskStatement) 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/parsers/json/task_statement_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe PuppetStrings::Yard::Parsers::JSON::TaskStatement do 6 | subject(:spec_subject) { described_class.new(json, source, 'test.json') } 7 | 8 | let(:source) { <<~SOURCE } 9 | { 10 | "description": "Allows you to backup your database to local file.", 11 | "input_method": "stdin", 12 | "parameters": { 13 | "database": { 14 | "description": "Database to connect to", 15 | "type": "Optional[String[1]]" 16 | }, 17 | "user": { 18 | "description": "The user", 19 | "type": "Optional[String[1]]" 20 | }, 21 | "password": { 22 | "description": "The password", 23 | "type": "Optional[String[1]]" 24 | }, 25 | "sql": { 26 | "description": "Path to file you want backup to", 27 | "type": "String[1]" 28 | } 29 | } 30 | } 31 | SOURCE 32 | let(:json) { JSON.parse(source) } 33 | 34 | describe '#comments' do 35 | it 'returns docstring' do 36 | expect(spec_subject.comments).to eq 'Allows you to backup your database to local file.' 37 | end 38 | end 39 | 40 | describe '#parameters' do 41 | context 'with params' do 42 | it 'returns params' do 43 | expect(!spec_subject.parameters.empty?).to be true 44 | end 45 | end 46 | 47 | context 'no params' do 48 | let(:source) { <<~SOURCE } 49 | { 50 | "description": "Allows you to backup your database to local file.", 51 | "input_method": "stdin" 52 | } 53 | SOURCE 54 | 55 | it 'returns an empty hash' do 56 | expect(spec_subject.parameters).to eq({}) 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /spec/unit/puppet-strings/yard/util_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require 'puppet-strings/yard' 5 | 6 | describe PuppetStrings::Yard::Util do 7 | subject(:spec_subject) { described_class } 8 | 9 | describe 'scrub_string' do 10 | it 'removes `%Q` and its brackets from a string' do 11 | str = '%Q{this is a test string}' 12 | expect(spec_subject.scrub_string(str)).to eq('this is a test string') 13 | end 14 | 15 | it 'removes `%q` and its brackets from a string' do 16 | str = '%q{this is a test string}' 17 | expect(spec_subject.scrub_string(str)).to eq('this is a test string') 18 | end 19 | 20 | it 'does not affect newlines when %Q notation is used' do 21 | str = <<~STR 22 | %Q{this is 23 | a test string} 24 | STR 25 | expect(spec_subject.scrub_string(str)).to eq("this is\na test string") 26 | end 27 | 28 | it 'does not affect a string which does not use %Q notation' do 29 | str = 'this is a test string' 30 | expect(spec_subject.scrub_string(str)).to eq('this is a test string') 31 | end 32 | end 33 | 34 | describe 'github_to_yard_links' do 35 | it 'converts a link correctly' do 36 | str = '' 37 | expect(spec_subject.github_to_yard_links(str)).to eq('') 38 | end 39 | 40 | it 'leaves other links with hashes alone' do 41 | str = '' 42 | expect(spec_subject.github_to_yard_links(str)).to eq(str) 43 | end 44 | 45 | it 'leaves plain text alone' do 46 | str = ' module-description' 47 | expect(spec_subject.github_to_yard_links(str)).to eq(' module-description') 48 | end 49 | end 50 | 51 | describe 'ast_to_text' do 52 | it 'converts a simple AST correctly' do 53 | model = Puppet::Pops::Parser::Parser.new.parse_string('class test {}').model 54 | expect(described_class.ast_to_text(model.body)).to eq('class test {}') 55 | end 56 | end 57 | end 58 | --------------------------------------------------------------------------------