Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: build

on:
Expand All @@ -16,10 +13,10 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [24.x]
node-version: [24.x, latest]

runs-on: ${{ matrix.os }}

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -30,9 +27,24 @@ jobs:
- run: npm run build --if-present
- run: npm test

- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coverage/lcov.info
build-go:

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
- name: Build
working-directory: go
run: go build ./...
- name: Test
working-directory: go
run: go test -v ./...
50 changes: 50 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.PHONY: all build test clean build-ts build-go test-ts test-go clean-ts clean-go publish-go tags-go tidy-go reset

all: build test

build: build-ts build-go

test: test-ts test-go

clean: clean-ts clean-go

# TypeScript
build-ts:
npm run build

test-ts:
npm test

clean-ts:
rm -rf dist dist-test

# Go
build-go:
cd go && go build ./...

test-go:
cd go && go test ./...

clean-go:
cd go && go clean -cache

# Publish Go module: make publish-go V=0.1.7
publish-go: test-go
@test -n "$(V)" || (echo "Usage: make publish-go V=x.y.z" && exit 1)
git add go/plugin.go
git commit -m "go: v$(V)"
git tag go/v$(V)
git push origin main go/v$(V)
if command -v gh >/dev/null 2>&1; then gh release create go/v$(V) --title "go/v$(V)" --notes "Go module release v$(V)"; fi

tidy-go:
cd go && go mod tidy

tags-go:
git tag -l 'go/v*' --sort=-version:refname

reset:
npm run reset
cd go && go clean -cache
cd go && go build ./...
cd go && go test -v ./...
64 changes: 38 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# @jsonic/csv (JSONIC syntax plugin)
# @jsonic/csv

This plugin allows the [Jsonic](https://jsonic.senecajs.org) JSON
parser to support csv syntax.
A [Jsonic](https://jsonic.senecajs.org) syntax plugin that parses
CSV text into objects or arrays, with support for headers, quoted
fields, custom delimiters, streaming, and strict/non-strict modes.
Available for TypeScript and Go.


[![npm version](https://img.shields.io/npm/v/@jsonic/csv.svg)](https://npmjs.com/package/@jsonic/csv)
Expand All @@ -15,33 +17,43 @@ parser to support csv syntax.
| ---------------------------------------------------- | --------------------------------------------------------------------------------------- |


## Quick example

<!--START:options-->
## Options
* _comment_: `null` (default: null) - comment
* _field_
* _empty_: `string` (default: ) - empty
* _exact_: `boolean` (default: false) - exact
* _names_: `any` (default: undefined) - names
* _nonameprefix_: `string` (default: field~) - nonameprefix
* _separation_: `null` (default: null) - separation
* _header_: `boolean` (default: true) - header
* _number_: `null` (default: null) - number
* _object_: `boolean` (default: true) - object
* _record_
* _empty_: `boolean` (default: false) - empty
* _separators_: `null` (default: null) - separators
* _stream_: `null` (default: null) - stream
* _strict_: `boolean` (default: true) - strict
* _string_
* _csv_: `null` (default: null) - csv
* _quote_: `string` (default: ") - quote
* _trim_: `null` (default: null) - trim
* _value_: `null` (default: null) - value
<!--END:options-->
**TypeScript**

```typescript
import { Jsonic } from 'jsonic'
import { Csv } from '@jsonic/csv'

const parse = Jsonic.make().use(Csv)

parse("name,age\nAlice,30\nBob,25")
// [{ name: 'Alice', age: '30' }, { name: 'Bob', age: '25' }]

parse('a,b\n1,"hello, world"')
// [{ a: '1', b: 'hello, world' }]
```

**Go**

```go
import csv "github.com/jsonicjs/csv/go"

result, _ := csv.Parse("name,age\nAlice,30\nBob,25")
// [{name:Alice age:30} {name:Bob age:25}]
```


## Documentation

Full documentation following the [Diataxis](https://diataxis.fr)
framework (tutorials, how-to guides, explanation, reference):

- [TypeScript documentation](doc/csv-ts.md)
- [Go documentation](doc/csv-go.md)


## License

Copyright (c) 2021-2025 Richard Rodger and other contributors,
[MIT License](LICENSE).
52 changes: 52 additions & 0 deletions csv-grammar.jsonic
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# CSV Grammar Definition
# Parsed by a standard Jsonic instance and passed to jsonic.grammar()
# Function references (@ prefixed) are resolved against the refs map
#
# Token naming:
# #LN - line ending (removed from per-instance IGNORE set)
# #SP - whitespace (removed from per-instance IGNORE set in strict mode)
# #CA - comma / field separator
# #ZZ - end of input
# #VAL - token set: text, string, number, value literals
#
# Rules csv, newline, record, text are fully defined here.
# Rules list, elem, val are modified in code (strict mode defines from scratch;
# non-strict prepends to existing defaults to preserve JSON parsing).

{
rule: csv: open: [
{ s: '#ZZ' }
{ s: '#LN' p: newline c: '@not-record-empty' }
{ p: record }
]

rule: newline: open: [
{ s: '#LN #LN' r: newline }
{ s: '#LN' r: newline }
{ s: '#ZZ' }
{ r: record }
]
rule: newline: close: [
{ s: '#LN #LN' r: newline }
{ s: '#LN' r: newline }
{ s: '#ZZ' }
{ r: record }
]

rule: record: open: [
{ p: list }
]
rule: record: close: [
{ s: '#ZZ' }
{ s: '#LN #ZZ' b: 1 }
{ s: '#LN' r: '@record-close-next' }
]

rule: text: open: [
{ s: ['#VAL' '#SP'] b: 1 r: text n: { text: 1 } g: 'csv,space,follows' a: '@text-follows' }
{ s: ['#SP' '#VAL'] r: text n: { text: 1 } g: 'csv,space,leads' a: '@text-leads' }
{ s: ['#SP' '#CA #LN #ZZ'] b: 1 n: { text: 1 } g: 'csv,end' a: '@text-end' }
{ s: '#SP' n: { text: 1 } g: 'csv,space' a: '@text-space' p: '@text-space-push' }
{}
]
}
Loading
Loading