Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Copilot

csv.html

learn how to use the CSV shortcode

The {{<csv>}} shortcode provides a simple way to embed CSV files in your documentation from a global static/csv directory. This approach works well for large and/or complex tables that you want to keep separate from your markdown files.

Using this shortcode also enables you to update your CSV files programmatically without needing to update the markdown files that reference them.

How it works

The {{<csv>}} shortcode accepts 3 positional arguments: filename, delimiter, and excludedColumns.

  • filename specifies the CSV file to embed. The file resides in the static/csv directory. You don’t need to include the .csv extension.
  • delimiter defines the character that separates columns in the CSV file. Default: ,.
  • excludedColumns accepts a comma-separated list of column numbers to exclude from the table. This parameter has case-sensitivity and defaults to an empty string.

Examples

The table in the following examples comes from /static/csv/food.csv.

Full table with default delimiter

{{<csv food>}}

Data from food
ItemTypeOrigin
AppleFruitUSA
BananaFruitEcuador
CarrotVegetableCanada
TomatoVegetableItaly
BreadGrainFrance
CheeseDairySwitzerland

Full table with excluded column

{{<csv food "," "Origin">}}

Data from food
ItemType
AppleFruit
BananaFruit
CarrotVegetable
TomatoVegetable
BreadGrain
CheeseDairy

Source code

go
{{- $filename := .Get 0 -}}
{{- $delimiter := .Get 1 | default "," -}}
{{- $skipColumns := split (.Get 2 | default "") "," -}}
{{- $cssClass := .Get 3 | default "table table--dense table--zebra table--glass table--rounded" -}}
{{- $lazyQuotes := .Get 4 | default false -}}

{{- $csvResource := resources.Get (printf "csv/%s.csv" $filename) -}}
{{- $csvContent := "" -}}

{{- if $csvResource -}}
    {{- $csvContent = $csvResource.Content -}}
{{- else -}}
    {{/* Fallback: try reading from static directory */}}
    {{- $staticPath := printf "static/csv/%s.csv" $filename -}}
    {{- $csvContent = readFile $staticPath -}}
    {{- if not $csvContent -}}
        {{- errorf "CSV shortcode: File not found in assets/csv/%s.csv or static/csv/%s.csv on page %s" $filename $filename .Page.RelPermalink -}}
        <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
            <strong>CSV Error:</strong> File "{{ $filename }}.csv" not found in assets/csv/ or static/csv/ directories.
        </div>
    {{- end -}}
{{- end -}}

{{- if $csvContent -}}
    {{- $unmarshalOptions := dict "delimiter" $delimiter -}}
    {{- if $lazyQuotes -}}
        {{- $unmarshalOptions = merge $unmarshalOptions (dict "lazyQuotes" true) -}}
    {{- end -}}
    
    {{- $csvData := "" -}}
    {{- if $csvResource -}}
        {{- $csvData = $csvResource | transform.Unmarshal $unmarshalOptions -}}
    {{- else -}}
        {{- $csvData = $csvContent | transform.Unmarshal $unmarshalOptions -}}
    {{- end -}}
    
    {{- if not $csvData -}}
        {{- errorf "CSV shortcode: Failed to parse CSV data from '%s' on page %s" $filename .Page.RelPermalink -}}
        <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
            <strong>CSV Error:</strong> Failed to parse CSV data from "{{ $filename }}". The file may be empty or incorrectly formatted.
        </div>
    {{- else if eq (len $csvData) 0 -}}
        {{- errorf "CSV shortcode: Empty CSV data from '%s' on page %s" $filename .Page.RelPermalink -}}
        <div class="bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded mb-4">
            <strong>CSV Warning:</strong> No data found in "{{ $filename }}".
        </div>
    {{- else -}}
        {{- $headers := index $csvData 0 -}}
        {{- $filteredHeaders := slice -}}
        {{- $filteredIndices := slice -}}
        
        {{- range $index, $col := $headers -}}
            {{- if not (in $skipColumns $col) -}}
                {{- $filteredHeaders = $filteredHeaders | append $col -}}
                {{- $filteredIndices = $filteredIndices | append $index -}}
            {{- end -}}
        {{- end -}}
        
        <div class="table__container table__container--rounded">
            <table class="{{ $cssClass }}" role="table">
                <caption class="sr-only">Data from {{ $filename }}</caption>
                <thead class="table__head">
                    <tr>
                    {{- range $filteredHeaders -}}
                        <th scope="col" class="table__cell">
                            {{- . | markdownify -}}
                        </th>
                    {{- end -}}
                    </tr>
                </thead>
                <tbody class="table__body">
                    {{- range $rowIndex, $row := after 1 $csvData -}}
                        <tr class="table__row">
                        {{- range $filteredIndices -}}
                            <td class="table__cell table__cell--nowrap">
                                {{- if lt . (len $row) -}}
                                    {{- index $row . | markdownify -}}
                                {{- else -}}
                                    <span class="text-gray-400"></span>
                                {{- end -}}
                            </td>
                        {{- end -}}
                        </tr>
                    {{- end -}}
                </tbody>
            </table>
        </div>
    {{- end -}}
{{- end -}}