csv.html

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>}}

Error: CSV file "food" not found in the csv directory.

Full table with excluded column

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

Error: CSV file "food" not found in the csv directory.

Source code

{{$filename := .Get 0}}
{{- $delimiter := .Get 1 | default "," -}}
{{- $skipColumns := split (.Get 2 | default "") "," -}}
{{- $csvResource := resources.Get (printf "csv/%s" $filename) -}}

{{- if not $csvResource -}}
    <div class="error">Error: CSV file "{{ $filename }}" not found in the csv directory.</div>
{{- else -}}
    {{- $csvData := $csvResource | transform.Unmarshal (dict "delimiter" $delimiter) -}}
    
    {{- if not $csvData -}}
        <div class="error">Error: Failed to parse CSV data from "{{ $filename }}". The file may be empty or incorrectly formatted.</div>
    {{- else -}}
        <div class="overflow-x-auto">
            <table class="min-w-full divide-y divide-zinc-200">
                <thead>
                    <tr>
                    {{- range $index, $col := index $csvData 0 -}}
                        {{- if not (in $skipColumns $col) -}}
                            <th scope="col" class="px-3 py-2 text-left text-sm font-semibold text-black uppercase tracking-wider">
                                {{- $col -}}
                            </th>
                        {{- end -}}
                    {{- end -}}
                    </tr>
                </thead>
                <tbody class="divide-y divide-zinc-200">
                    {{- range $rowIndex, $row := after 1 $csvData -}}
                        <tr class="{{ cond (modBool $rowIndex 2) "bg-zinc-50" "bg-white" }}">
                        {{- range $colIndex, $col := $row -}}
                            {{- if not (in $skipColumns (index (index $csvData 0) $colIndex)) -}}
                                <td class="px-3 py-2 whitespace-nowrap text-sm text-black">
                                    {{- $col | markdownify -}}
                                </td>
                            {{- end -}}
                        {{- end -}}
                        </tr>
                    {{- end -}}
                </tbody>
            </table>
        </div>
    {{- end -}}
{{- end -}}