mirror of
https://github.com/parsecsv/csv-spec.org.git
synced 2026-02-19 00:46:40 +00:00
Initial commit
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
_site
|
||||
.asset-cache
|
||||
.sass-cache
|
||||
.jekyll-metadata
|
||||
docs/assets/.sprockets-manifest-*.json
|
||||
9
404.html
Normal file
9
404.html
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: 404 Page Not Found
|
||||
sitemap: false
|
||||
---
|
||||
<div class="header">
|
||||
<h1>404</h1>
|
||||
<p><strong>Page not found :(</strong></p>
|
||||
<p>The requested page could not be found.</p>
|
||||
</div>
|
||||
21
Gemfile
Normal file
21
Gemfile
Normal file
@@ -0,0 +1,21 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'jekyll', '3.5.0'
|
||||
|
||||
group :development do
|
||||
gem 'rake'
|
||||
gem 'rubocop'
|
||||
end
|
||||
|
||||
# If you have any plugins, put them here!
|
||||
group :jekyll_plugins do
|
||||
gem 'jekyll-assets'
|
||||
gem 'jekyll-pants'
|
||||
gem 'jekyll-seo-tag'
|
||||
gem 'jekyll-sitemap'
|
||||
gem 'jekyll-tidy'
|
||||
gem 'uglifier' # required by 'jekyll-assets' for JS compression
|
||||
end
|
||||
|
||||
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
||||
102
Gemfile.lock
Normal file
102
Gemfile.lock
Normal file
@@ -0,0 +1,102 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.5.1)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
ast (2.3.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.0.5)
|
||||
execjs (2.7.0)
|
||||
extras (0.3.0)
|
||||
forwardable-extended (~> 2.5)
|
||||
fastimage (2.1.0)
|
||||
ffi (1.9.18)
|
||||
forwardable-extended (2.6.0)
|
||||
htmlbeautifier (1.3.1)
|
||||
htmlcompressor (0.3.1)
|
||||
jekyll (3.5.0)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 1.1)
|
||||
kramdown (~> 1.3)
|
||||
liquid (~> 4.0)
|
||||
mercenary (~> 0.3.3)
|
||||
pathutil (~> 0.9)
|
||||
rouge (~> 1.7)
|
||||
safe_yaml (~> 1.0)
|
||||
jekyll-assets (2.3.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
extras (~> 0.2)
|
||||
fastimage (~> 2.0, >= 1.8)
|
||||
jekyll (~> 3.1, >= 3.0)
|
||||
pathutil (>= 0.8)
|
||||
rack (~> 1.6)
|
||||
sprockets (~> 3.3, < 3.8)
|
||||
jekyll-pants (0.2.1)
|
||||
rubypants
|
||||
jekyll-sass-converter (1.5.0)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.2.3)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sitemap (1.0.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-tidy (0.2.2)
|
||||
htmlbeautifier
|
||||
htmlcompressor
|
||||
jekyll
|
||||
jekyll-watch (1.5.0)
|
||||
listen (~> 3.0, < 3.1)
|
||||
kramdown (1.14.0)
|
||||
liquid (4.0.0)
|
||||
listen (3.0.8)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
mercenary (0.3.6)
|
||||
parser (2.4.0.0)
|
||||
ast (~> 2.2)
|
||||
pathutil (0.14.0)
|
||||
forwardable-extended (~> 2.6)
|
||||
powerpack (0.1.1)
|
||||
public_suffix (2.0.5)
|
||||
rack (1.6.8)
|
||||
rainbow (2.2.1)
|
||||
rake (12.0.0)
|
||||
rb-fsevent (0.10.2)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
rouge (1.11.1)
|
||||
rubocop (0.47.1)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-progressbar (1.8.1)
|
||||
rubypants (0.6.0)
|
||||
safe_yaml (1.0.4)
|
||||
sass (3.4.25)
|
||||
sprockets (3.7.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
uglifier (3.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (1.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
jekyll (= 3.5.0)
|
||||
jekyll-assets
|
||||
jekyll-pants
|
||||
jekyll-seo-tag
|
||||
jekyll-sitemap
|
||||
jekyll-tidy
|
||||
rake
|
||||
rubocop
|
||||
tzinfo-data
|
||||
uglifier
|
||||
|
||||
BUNDLED WITH
|
||||
1.14.6
|
||||
5
README.md
Normal file
5
README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# csv-spec.org
|
||||
|
||||
This is the site at http://csv-spec.org/ that attempts to describe CSV-like
|
||||
formats in a obvious and easy to understand way, complete with code examples
|
||||
aimed at developers.
|
||||
85
Rakefile
Normal file
85
Rakefile
Normal file
@@ -0,0 +1,85 @@
|
||||
require 'open-uri'
|
||||
require 'yaml'
|
||||
|
||||
desc 'Build site into docs directory'
|
||||
task :build do
|
||||
jekyll_build
|
||||
end
|
||||
|
||||
desc 'Update index.md and spec folder based on versions in _config.yml'
|
||||
task :update do
|
||||
config = YAML.load_file('_config.yml')
|
||||
current_version = config['current_version']
|
||||
versions = config['versions']
|
||||
|
||||
remove_all_specs(config['update'])
|
||||
|
||||
puts ''
|
||||
puts 'Fetching configured spec versions:'
|
||||
versions.each do |version|
|
||||
spec = fetch_spec(version, config['update'])
|
||||
|
||||
if current_version == version
|
||||
write_file('index.md', spec[:body], " (#{version})")
|
||||
end
|
||||
|
||||
filename = File.join(config['update']['output_dir'], version)
|
||||
write_file("#{filename}.md", spec[:body])
|
||||
write_file("#{filename}.svg", spec[:diagram]) if spec[:diagram]
|
||||
end
|
||||
|
||||
jekyll_build
|
||||
end
|
||||
|
||||
def jekyll_build
|
||||
puts 'Rebuilding output into docs directory...'
|
||||
exec 'jekyll build --destination docs && touch docs/.nojekyll'
|
||||
end
|
||||
|
||||
def write_file(file, content, comment = nil)
|
||||
puts " - #{file}#{comment}"
|
||||
File.write(file, content)
|
||||
end
|
||||
|
||||
def fetch_spec(version, config)
|
||||
document = get(build_file_url('document', version, config))
|
||||
|
||||
if config['files']['diagram']
|
||||
diagram = get(build_file_url('diagram', version, config))
|
||||
img_tag = config['img_tpl'].gsub('{{file}}', "#{version}.svg")
|
||||
document.gsub!(/\A(.*\n=+\n)/, "\\1\n#{img_tag}\n")
|
||||
end
|
||||
|
||||
title = document.split("\n", 2).first
|
||||
body = config['body_tpl'].gsub('{{content}}', document)
|
||||
.gsub('{{title}}', title)
|
||||
.gsub('{{version}}', version)
|
||||
|
||||
{
|
||||
version: version,
|
||||
title: title,
|
||||
body: body,
|
||||
diagram: diagram
|
||||
}
|
||||
end
|
||||
|
||||
def build_file_url(file, version, config)
|
||||
config['url_tpl']
|
||||
.gsub('{{version}}', version)
|
||||
.gsub('{{file}}', config['files'][file])
|
||||
end
|
||||
|
||||
def get(url)
|
||||
URI.parse(url).read
|
||||
rescue OpenURI::HTTPError
|
||||
nil
|
||||
end
|
||||
|
||||
def remove_all_specs(config)
|
||||
puts ''
|
||||
puts 'Removing existing spec files:'
|
||||
Dir["#{config['output_dir']}/*"].each do |file|
|
||||
puts " #{file.gsub(File.dirname(__FILE__), '')}"
|
||||
File.delete(file)
|
||||
end
|
||||
end
|
||||
90
_assets/css/_base.scss
Normal file
90
_assets/css/_base.scss
Normal file
@@ -0,0 +1,90 @@
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Open Sans Condensed', Helvetica, Arial, sans-serif;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ol ol, ul ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
||||
ul ul ol, ul ol ol, ol ul ol, ol ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 80px;
|
||||
|
||||
a {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: rgba(27,31,35,0.05);
|
||||
border-radius: 3px;
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
padding: 0.3em 0.4em 0.1em 0.4em;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f6f8fa;
|
||||
border-radius: 3px;
|
||||
line-height: 1.45;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
background-color: transparent !important;
|
||||
border-radius: none;
|
||||
font-size: 90%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#menu {
|
||||
.pure-menu-label {
|
||||
color: #999;
|
||||
border: none;
|
||||
padding: 0.6em 0 0.6em 0.6em;
|
||||
}
|
||||
|
||||
.links {
|
||||
font-size: 50px;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: #555;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
_assets/css/_highlight.scss
Normal file
62
_assets/css/_highlight.scss
Normal file
@@ -0,0 +1,62 @@
|
||||
/* https://github.com/jwarby/jekyll-pygments-themes/blob/22dfd74f9f10c87c0ec98876e136f02c989d43ba/github.css */
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||
.highlight .k { color: #000000; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #000000; font-weight: bold } /* Operator */
|
||||
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #000000; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .m { color: #009999 } /* Literal.Number */
|
||||
.highlight .s { color: #d01040 } /* Literal.String */
|
||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #008080 } /* Name.Constant */
|
||||
.highlight .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.highlight .nl { color: #990000; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #d01040 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #d01040 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #d01040 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #d01040 } /* Literal.String.Double */
|
||||
.highlight .se { color: #d01040 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #d01040 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #d01040 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #d01040 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #d01040 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||
248
_assets/css/_side-menu.scss
Normal file
248
_assets/css/_side-menu.scss
Normal file
@@ -0,0 +1,248 @@
|
||||
body {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.pure-img-responsive {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
Add transition to containers so they can push in and out.
|
||||
*/
|
||||
#layout,
|
||||
#menu,
|
||||
.menu-link {
|
||||
-webkit-transition: all 0.2s ease-out;
|
||||
-moz-transition: all 0.2s ease-out;
|
||||
-ms-transition: all 0.2s ease-out;
|
||||
-o-transition: all 0.2s ease-out;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the parent `<div>` that contains the menu and the content area.
|
||||
*/
|
||||
#layout {
|
||||
position: relative;
|
||||
left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
#layout.active #menu {
|
||||
left: 150px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#layout.active .menu-link {
|
||||
left: 150px;
|
||||
}
|
||||
/*
|
||||
The content `<div>` is where all your content goes.
|
||||
*/
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
padding: 0 2em;
|
||||
max-width: 800px;
|
||||
margin-bottom: 50px;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin: 0;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
padding: 2.5em 2em 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0.2em 0;
|
||||
font-size: 3em;
|
||||
font-weight: 300;
|
||||
}
|
||||
.header h2 {
|
||||
font-weight: 300;
|
||||
color: #ccc;
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.content-subhead {
|
||||
margin: 50px 0 20px 0;
|
||||
font-weight: 300;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
The `#menu` `<div>` is the parent `<div>` that contains the `.pure-menu` that
|
||||
appears on the left side of the page.
|
||||
*/
|
||||
|
||||
#menu {
|
||||
margin-left: -150px; /* "#menu" width */
|
||||
width: 150px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000; /* so the menu or its navicon stays above all content */
|
||||
background: #191818;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
/*
|
||||
All anchors inside the menu should be styled like this.
|
||||
*/
|
||||
#menu a {
|
||||
color: #999;
|
||||
border: none;
|
||||
padding: 0.6em 0 0.6em 0.6em;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove all background/borders, since we are applying them to #menu.
|
||||
*/
|
||||
#menu .pure-menu,
|
||||
#menu .pure-menu ul {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/*
|
||||
Add that light border to separate items into groups.
|
||||
*/
|
||||
#menu .pure-menu ul,
|
||||
#menu .pure-menu .menu-item-divided {
|
||||
border-top: 1px solid #333;
|
||||
}
|
||||
/*
|
||||
Change color of the anchor links on hover/focus.
|
||||
*/
|
||||
#menu .pure-menu li a:hover,
|
||||
#menu .pure-menu li a:focus {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles the selected menu item `<li>`.
|
||||
*/
|
||||
#menu .pure-menu-selected,
|
||||
#menu .pure-menu-heading {
|
||||
background: #1f8dd6;
|
||||
}
|
||||
/*
|
||||
This styles a link within a selected menu item `<li>`.
|
||||
*/
|
||||
#menu .pure-menu-selected a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles the menu heading.
|
||||
*/
|
||||
#menu .pure-menu-heading {
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
|
||||
|
||||
/*
|
||||
The button to open/close the Menu is custom-made and not part of Pure. Here's
|
||||
how it works:
|
||||
*/
|
||||
|
||||
/*
|
||||
`.menu-link` represents the responsive menu toggle that shows/hides on
|
||||
small screens.
|
||||
*/
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
display: block; /* show this only on small screens */
|
||||
top: 0;
|
||||
left: 0; /* "#menu width" */
|
||||
background: #000;
|
||||
background: rgba(0,0,0,0.7);
|
||||
font-size: 10px; /* change this value to increase/decrease button size */
|
||||
z-index: 10;
|
||||
width: 2em;
|
||||
height: auto;
|
||||
padding: 2.1em 1.6em;
|
||||
}
|
||||
|
||||
.menu-link:hover,
|
||||
.menu-link:focus {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.menu-link span {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu-link span,
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 0.2em;
|
||||
}
|
||||
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
position: absolute;
|
||||
margin-top: -0.6em;
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.menu-link span:after {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
|
||||
/* -- Responsive Styles (Media Queries) ------------------------------------- */
|
||||
|
||||
/*
|
||||
Hides the menu at `48em`, but modify this based on your app's needs.
|
||||
*/
|
||||
@media (min-width: 48em) {
|
||||
|
||||
.header,
|
||||
.content {
|
||||
padding-left: 2em;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
#layout {
|
||||
padding-left: 150px; /* left col width "#menu" */
|
||||
left: 0;
|
||||
}
|
||||
#menu {
|
||||
left: 150px;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
left: 150px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#layout.active .menu-link {
|
||||
left: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 48em) {
|
||||
/* Only apply this when the window is small. Otherwise, the following
|
||||
case results in extra padding on the left:
|
||||
* Make the window small.
|
||||
* Tap the menu to trigger the active state.
|
||||
* Make the window large again.
|
||||
*/
|
||||
#layout.active {
|
||||
position: relative;
|
||||
left: 150px;
|
||||
}
|
||||
}
|
||||
3
_assets/css/main.scss
Normal file
3
_assets/css/main.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
@import "side-menu";
|
||||
@import "highlight";
|
||||
@import "base";
|
||||
1
_assets/js/main.js
Normal file
1
_assets/js/main.js
Normal file
@@ -0,0 +1 @@
|
||||
// = require ui
|
||||
44
_assets/js/ui.js
Normal file
44
_assets/js/ui.js
Normal file
@@ -0,0 +1,44 @@
|
||||
(function (window, document) {
|
||||
var layout = document.getElementById('layout');
|
||||
var menu = document.getElementById('menu');
|
||||
var menuLink = document.getElementById('menuLink');
|
||||
var content = document.getElementById('main');
|
||||
|
||||
function toggleClass (element, className) {
|
||||
var classes = element.className.split(/\s+/);
|
||||
var length = classes.length;
|
||||
var i = 0;
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (classes[i] === className) {
|
||||
classes.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The className is not found
|
||||
if (length === classes.length) {
|
||||
classes.push(className);
|
||||
}
|
||||
|
||||
element.className = classes.join(' ');
|
||||
}
|
||||
|
||||
function toggleAll (e) {
|
||||
var active = 'active';
|
||||
|
||||
e.preventDefault();
|
||||
toggleClass(layout, active);
|
||||
toggleClass(menu, active);
|
||||
toggleClass(menuLink, active);
|
||||
}
|
||||
|
||||
menuLink.onclick = function (e) {
|
||||
toggleAll(e);
|
||||
};
|
||||
|
||||
content.onclick = function (e) {
|
||||
if (menu.className.indexOf('active') !== -1) {
|
||||
toggleAll(e);
|
||||
}
|
||||
};
|
||||
}(this, this.document));
|
||||
50
_config.yml
Normal file
50
_config.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
title: CSV Spec
|
||||
description: >
|
||||
An attempt to describe CSV-like formats in a obvious and easy to understand
|
||||
way, complete with code examples aimed at developers.
|
||||
author: Jim Myhrberg
|
||||
hostname: csv-spec.org
|
||||
url: https://csv-spec.org
|
||||
repo_url: https://github.com/parsecsv/csv-spec
|
||||
|
||||
current_version: 0.9.0-draft.1
|
||||
versions:
|
||||
- 0.9.0-draft.1
|
||||
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- Rakefile
|
||||
- README.md
|
||||
|
||||
update:
|
||||
body_tpl: |
|
||||
---
|
||||
title: {{title}}
|
||||
version: {{version}}
|
||||
---
|
||||
{{content}}
|
||||
url_tpl: "https://github.com/parsecsv/csv-spec/raw/{{version}}/{{file}}"
|
||||
output_dir: "spec"
|
||||
files:
|
||||
document: csv-spec.md
|
||||
|
||||
plugins:
|
||||
- jekyll-assets
|
||||
- jekyll-pants
|
||||
- jekyll-sitemap
|
||||
- jekyll-seo-tag
|
||||
- jekyll-tidy
|
||||
|
||||
defaults:
|
||||
-
|
||||
scope:
|
||||
path: ""
|
||||
values:
|
||||
layout: "default"
|
||||
|
||||
assets:
|
||||
digest: true
|
||||
compress:
|
||||
css: true
|
||||
js: true
|
||||
54
_layouts/default.html
Normal file
54
_layouts/default.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300|Open+Sans:400italic,700italic,400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https:////maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
{% css main %}
|
||||
{% seo %}
|
||||
</head>
|
||||
<body>
|
||||
<div id="layout">
|
||||
<a href="#menu" id="menuLink" class="menu-link">
|
||||
<span></span>
|
||||
</a>
|
||||
<div id="menu">
|
||||
<div class="pure-menu">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item">
|
||||
<div class="pure-menu-label">Versions:</div>
|
||||
</li>
|
||||
{% for version in site.versions %}
|
||||
{% assign expected = "spec/" | append: version | append: ".md" %}
|
||||
{% assign found = site.pages | where: "path", expected | first %}
|
||||
{% assign selected = "" %}
|
||||
{% if version == page.version %}
|
||||
{% assign selected = " pure-menu-selected" %}
|
||||
{% endif %}
|
||||
{% if found %}
|
||||
<li class="pure-menu-item version-{{ version }}{{ selected }}">
|
||||
<a href="{{ found.url }}" class="pure-menu-link">{{ version }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="{{ site.repo_url }}">
|
||||
<i class="fa fa-github" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main">
|
||||
<div class="content">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% js main %}
|
||||
</body>
|
||||
</html>
|
||||
0
docs/.nojekyll
Normal file
0
docs/.nojekyll
Normal file
60
docs/404.html
Normal file
60
docs/404.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300|Open+Sans:400italic,700italic,400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https:////maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/assets/main-5df19fc13b2a391dcab974f0584820f95eecdd416e60b99950f2058c61a2e99f.css">
|
||||
<!-- Begin Jekyll SEO tag v2.2.3 -->
|
||||
<title>404 Page Not Found | CSV Spec</title>
|
||||
<meta property="og:title" content="404 Page Not Found" />
|
||||
<meta name="author" content="Jim Myhrberg" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta name="description" content="An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers." />
|
||||
<meta property="og:description" content="An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers." />
|
||||
<link rel="canonical" href="https://csv-spec.org/404.html" />
|
||||
<meta property="og:url" content="https://csv-spec.org/404.html" />
|
||||
<meta property="og:site_name" content="CSV Spec" />
|
||||
<script type="application/ld+json">
|
||||
{"@context":"http://schema.org","@type":"WebPage","headline":"404 Page Not Found","author":{"@type":"Person","name":"Jim Myhrberg"},"description":"An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers.","url":"https://csv-spec.org/404.html"}
|
||||
</script>
|
||||
<!-- End Jekyll SEO tag -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="layout">
|
||||
<a href="#menu" id="menuLink" class="menu-link">
|
||||
<span></span>
|
||||
</a>
|
||||
<div id="menu">
|
||||
<div class="pure-menu">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item">
|
||||
<div class="pure-menu-label">Versions:</div>
|
||||
</li>
|
||||
<li class="pure-menu-item version-0.9.0-draft.1">
|
||||
<a href="/spec/0.9.0-draft.1.html" class="pure-menu-link">0.9.0-draft.1</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/parsecsv/csv-spec">
|
||||
<i class="fa fa-github" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="content">
|
||||
<div class="header">
|
||||
<h1>404</h1>
|
||||
<p><strong>Page not found :(</strong></p>
|
||||
<p>The requested page could not be found.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/assets/main-870855580c69dec57be4c965d0cf8afe78afa6b7b6f6bdb5aff91ac0256c0a1a.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
csv-spec.org
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,n){function t(e,n){for(var t=e.className.split(/\s+/),i=t.length,c=0;c<i;c++)if(t[c]===n){t.splice(c,1);break}i===t.length&&t.push(n),e.className=t.join(" ")}function i(e){var n="active";e.preventDefault(),t(c,n),t(a,n),t(l,n)}var c=n.getElementById("layout"),a=n.getElementById("menu"),l=n.getElementById("menuLink"),m=n.getElementById("main");l.onclick=function(e){i(e)},m.onclick=function(e){-1!==a.className.indexOf("active")&&i(e)}}(0,this.document);
|
||||
308
docs/index.html
Normal file
308
docs/index.html
Normal file
@@ -0,0 +1,308 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300|Open+Sans:400italic,700italic,400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https:////maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/assets/main-5df19fc13b2a391dcab974f0584820f95eecdd416e60b99950f2058c61a2e99f.css">
|
||||
<!-- Begin Jekyll SEO tag v2.2.3 -->
|
||||
<title>CSV Spec 0.9.0-draft.1 | CSV Spec</title>
|
||||
<meta property="og:title" content="CSV Spec 0.9.0-draft.1" />
|
||||
<meta name="author" content="Jim Myhrberg" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta name="description" content="An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers." />
|
||||
<meta property="og:description" content="An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers." />
|
||||
<link rel="canonical" href="https://csv-spec.org/" />
|
||||
<meta property="og:url" content="https://csv-spec.org/" />
|
||||
<meta property="og:site_name" content="CSV Spec" />
|
||||
<script type="application/ld+json">
|
||||
{"@context":"http://schema.org","@type":"WebSite","name":"CSV Spec","headline":"CSV Spec 0.9.0-draft.1","author":{"@type":"Person","name":"Jim Myhrberg"},"description":"An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers.","url":"https://csv-spec.org/"}
|
||||
</script>
|
||||
<!-- End Jekyll SEO tag -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="layout">
|
||||
<a href="#menu" id="menuLink" class="menu-link">
|
||||
<span></span>
|
||||
</a>
|
||||
<div id="menu">
|
||||
<div class="pure-menu">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item">
|
||||
<div class="pure-menu-label">Versions:</div>
|
||||
</li>
|
||||
<li class="pure-menu-item version-0.9.0-draft.1 pure-menu-selected">
|
||||
<a href="/spec/0.9.0-draft.1.html" class="pure-menu-link">0.9.0-draft.1</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/parsecsv/csv-spec">
|
||||
<i class="fa fa-github" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="content">
|
||||
<h1 id="csv-spec-090-draft1">CSV Spec 0.9.0-draft.1</h1>
|
||||
<h2 id="summary">Summary</h2>
|
||||
<p>CSV is not a file format, it is a loose set of guidelines of how to structure
|
||||
tabular data into a plain text string. As such there’s an endless amount of
|
||||
<code class="highlighter-rouge">*.csv</code> files floating around which are highly incompatible with each other. The
|
||||
closest thing there is to a specification is <a href="http://tools.ietf.org/html/rfc4180">RFC
|
||||
4180</a>.</p>
|
||||
<h2 id="goals">Goals</h2>
|
||||
<p>This project is an attempt to summarize RFC 4180 and the information in the
|
||||
<a href="http://en.wikipedia.org/wiki/Comma-separated_values">Comma-separated values
|
||||
(CSV)</a> Wikipedia article
|
||||
into a easy to understand format. The spec will also take into account that the
|
||||
comma (<code class="highlighter-rouge">,</code>) character is not the only character used as a field
|
||||
delimiter. Semi-colons (<code class="highlighter-rouge">;</code>), tabs (<code class="highlighter-rouge">\t</code>), and more are popular field delimiter
|
||||
characters. As such the specification will more accurately be describing a
|
||||
CSV-like structured data format.</p>
|
||||
<p>We will also provide input/output test files that CSV parser/writer software
|
||||
libraries can use to validate if they properly adhere to the rules laid out in
|
||||
this specification. And if possible we will even try to provide code snippets in
|
||||
various languages that attempts to automatically determine the delimiter
|
||||
character used in any given input CSV-like formatted file/data.</p>
|
||||
<h2 id="roadmap">Roadmap</h2>
|
||||
<ol>
|
||||
<li>Write up core specification rules. <em>[in-progress]</em></li>
|
||||
<li>Create input/output test files covering all rules in the specification.</li>
|
||||
<li>Create website for <a href="http://csv-spec.org/">csv-spec.org</a>.</li>
|
||||
<li>Create linting tool as a NPM module, allowing easy validation of CSV data
|
||||
both client-side in a web browser, and server side via a command line tool.</li>
|
||||
<li>Create automatic delimiter character detection code snippets in various
|
||||
programming languages which CSV parser developers can freely use to enhance
|
||||
their libraries.</li>
|
||||
</ol>
|
||||
<h2 id="terminology">Terminology</h2>
|
||||
<ul>
|
||||
<li><strong>Field</strong> — A singular String value within a record.</li>
|
||||
<li><strong>Record</strong> (or <strong>Row</strong>) — A collection of fields. This is often referred to as
|
||||
a “line”, but a single record can span multiple text lines if a field within
|
||||
it contains one or more line breaks.</li>
|
||||
<li><strong>Delimiter</strong> — The character used to separate fields withing a row. Commonly
|
||||
this will be a comma (<code class="highlighter-rouge">,</code>), but semi-colons (<code class="highlighter-rouge">;</code>) or tabs (<code class="highlighter-rouge">\t</code>) are two other
|
||||
popular delimiter characters.</li>
|
||||
<li><strong>Header</strong> — The first row is often used to contain the column names for all
|
||||
remaining rows. Header names would be used as key names when CSV data is
|
||||
converted to JSON for example.</li>
|
||||
<li><strong>Line Break</strong> — Line breaks in CSV files can be CRLF (<code class="highlighter-rouge">\r\n</code>), LF (<code class="highlighter-rouge">\n</code>), and
|
||||
even in rare cases CR (<code class="highlighter-rouge">\r</code>).</li>
|
||||
<li><strong>LF, CR, and CRLF</strong> — Different types of line breaks, typically determined by
|
||||
the OS. Linux, OSX, and other *NIX operating systems generally use a line feed
|
||||
(LF or <code class="highlighter-rouge">\n</code>) character. Windows uses a carriage return (CR or <code class="highlighter-rouge">\r</code>) and a line
|
||||
feed character, effectively “CRLF” (<code class="highlighter-rouge">\r\n</code>).</li>
|
||||
</ul>
|
||||
<h2 id="csv-format-specification">CSV Format Specification</h2>
|
||||
<p>The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
|
||||
“SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be
|
||||
interpreted as described in <a href="https://tools.ietf.org/html/rfc2119">RFC 2119</a>.</p>
|
||||
<p>These rules are mostly based on the corresponding section from <a href="http://tools.ietf.org/html/rfc4180#section-2">RFC
|
||||
4180</a>, with minor changes,
|
||||
clarifications and improved examples.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Each record starts at the beginning of its own line, and ends with a line
|
||||
break (shown as <code class="highlighter-rouge">¬</code>).</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Though it is RECOMMENDED, the last record in a file is not required to have a
|
||||
ending line break.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>There may be an OPTIONAL header line appearing as the first line of the file
|
||||
with the same format as normal records. This header will contain names
|
||||
corresponding to the fields in the file, and MUST contain the same number of
|
||||
fields as the records in the rest of the file.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">field_1,field_2,field_3¬
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON (ignoring headers):</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"field_1"</span><span class="p">,</span><span class="w"> </span><span class="s2">"field_2"</span><span class="p">,</span><span class="w"> </span><span class="s2">"field_3"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
<p>JSON (using headers):</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="nt">"field_1"</span><span class="p">:</span><span class="w"> </span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_2"</span><span class="p">:</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">},</span><span class="w">
|
||||
</span><span class="p">{</span><span class="nt">"field_1"</span><span class="p">:</span><span class="w"> </span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_2"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Within each record and the OPTIONAL header, there may be one or more fields,
|
||||
separated by a delimiter (normally a comma). Each record MUST contain the
|
||||
same number of fields throughout the file.</p>
|
||||
<p>CSV (invalid):</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
111,222,333,444¬
|
||||
xxx,yyy,zzz¬
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>The last field in a record MUST NOT be followed by a comma. This results in a
|
||||
additional field with nothing in it.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc,¬
|
||||
xxx,yyy,zzz,¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Spaces are considered part of a field and MUST NOT be ignored.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa , bbb , ccc¬
|
||||
xxx, yyy ,zzz ¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa "</span><span class="p">,</span><span class="w"> </span><span class="s2">" bbb "</span><span class="p">,</span><span class="w"> </span><span class="s2">" ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">" xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">" yyy "</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz "</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Fields containing line breaks (CRLF, LF, or CR), double quotes, or the
|
||||
delimiter character (normally a comma) MUST be enclosed in double-quotes.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,"b¬
|
||||
bb",ccc¬
|
||||
xxx,"y, yy",zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"b\r\nbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"y, yy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>A double-quote appearing inside a field MUST be escaped by preceding it with
|
||||
another double quote, and the field itself MUST be enclosed in double quotes.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,"b""bb",ccc¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"b\"bb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a field enclosed in double quotes has spaces before and/or after the
|
||||
double quotes, the spaces MUST be ignored, as the field starts and ends with
|
||||
the double quotes. However this is considered invalid formatting and the CSV
|
||||
parser SHOULD report some form of warning message.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
xxx, "y, yy" ,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"y, yy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>It is possible to enclose every field in double quotes even if they don’t
|
||||
need to be enclosed. However it is RECOMMENDED to only enclose fields in
|
||||
double quotes that requires it.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">"aaa","bbb","ccc"¬
|
||||
"xxx",yyy,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>All fields are always strings. CSV itself does not support type casting to
|
||||
integers, floats, booleans, or anything else. It is not a CSV library’s
|
||||
responsibility to type cast input CSV data.</p>
|
||||
<p>If type casting is required, it is up to the developer using a specific CSV
|
||||
library to ensure types are correctly dealt with.</p>
|
||||
<p>Input JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="mf">0.3</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="s2">"aaa"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="mi">11</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="mf">2.13</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
<p>Output CSV:</p>
|
||||
<pre><code class="language-csv">10,true,0.3,,aaa¬
|
||||
11,false,2.13,,bbb¬
|
||||
</code></pre>
|
||||
<p>Output CSV parsed back to JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"10"</span><span class="p">,</span><span class="w"> </span><span class="s2">"true"</span><span class="p">,</span><span class="w"> </span><span class="s2">"0.3"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="s2">"aaa"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"11"</span><span class="p">,</span><span class="w"> </span><span class="s2">"false"</span><span class="p">,</span><span class="w"> </span><span class="s2">"2.13"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
<p>At this point it is up to the developer themselves to type cast the above
|
||||
output data from the CSV parser.</p>
|
||||
</li>
|
||||
<li>However, when rendering type cast input data to CSV text, non-string types
|
||||
MUST be converted to a string in such a way that minimal information is
|
||||
lost.
|
||||
<ul>
|
||||
<li>Integers and floats MUST be rendered as a string version of themselves.</li>
|
||||
<li>Booleans <code class="highlighter-rouge">true</code> and <code class="highlighter-rouge">false</code> MUST be rendered as <code class="highlighter-rouge">true</code> and <code class="highlighter-rouge">false</code>
|
||||
strings, not as <code class="highlighter-rouge">1</code> or <code class="highlighter-rouge">0</code> numbers. If numbers are used the resulting
|
||||
CSV data is indistinguishable from actual integer numbers.</li>
|
||||
<li><code class="highlighter-rouge">Null</code>/<code class="highlighter-rouge">nil</code> values MUST be rendered as empty strings.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>When parsing input CSV data all forms of line breaks (CRLF, LF, and CR) MUST
|
||||
be supported.</li>
|
||||
<li>When rendering output CSV data, CRLF MUST be used for line breaks to ensure
|
||||
maximum cross-platform compatibility.</li>
|
||||
</ol>
|
||||
<h2 id="about">About</h2>
|
||||
<p>This CSV specification is authored by <a href="https://jimeh.me/">Jim Myhrberg</a>.</p>
|
||||
<p>If you’d like to leave feedback,
|
||||
please <a href="https://github.com/parsecsv/csv-spec/issues">open an issue on GitHub</a>.</p>
|
||||
<h2 id="license">License</h2>
|
||||
<p><a href="http://creativecommons.org/publicdomain/zero/1.0/">CC0 1.0 Universal</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/assets/main-870855580c69dec57be4c965d0cf8afe78afa6b7b6f6bdb5aff91ac0256c0a1a.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
1
docs/robots.txt
Normal file
1
docs/robots.txt
Normal file
@@ -0,0 +1 @@
|
||||
Sitemap: https://csv-spec.org/sitemap.xml
|
||||
9
docs/sitemap.xml
Normal file
9
docs/sitemap.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://csv-spec.org/spec/0.9.0-draft.1.html</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://csv-spec.org/</loc>
|
||||
</url>
|
||||
</urlset>
|
||||
308
docs/spec/0.9.0-draft.1.html
Normal file
308
docs/spec/0.9.0-draft.1.html
Normal file
@@ -0,0 +1,308 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300|Open+Sans:400italic,700italic,400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https:////maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/assets/main-5df19fc13b2a391dcab974f0584820f95eecdd416e60b99950f2058c61a2e99f.css">
|
||||
<!-- Begin Jekyll SEO tag v2.2.3 -->
|
||||
<title>CSV Spec 0.9.0-draft.1 | CSV Spec</title>
|
||||
<meta property="og:title" content="CSV Spec 0.9.0-draft.1" />
|
||||
<meta name="author" content="Jim Myhrberg" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta name="description" content="An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers." />
|
||||
<meta property="og:description" content="An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers." />
|
||||
<link rel="canonical" href="https://csv-spec.org/spec/0.9.0-draft.1.html" />
|
||||
<meta property="og:url" content="https://csv-spec.org/spec/0.9.0-draft.1.html" />
|
||||
<meta property="og:site_name" content="CSV Spec" />
|
||||
<script type="application/ld+json">
|
||||
{"@context":"http://schema.org","@type":"WebPage","headline":"CSV Spec 0.9.0-draft.1","author":{"@type":"Person","name":"Jim Myhrberg"},"description":"An attempt to describe CSV-like formats in a obvious and easy to understand way, complete with code examples aimed at developers.","url":"https://csv-spec.org/spec/0.9.0-draft.1.html"}
|
||||
</script>
|
||||
<!-- End Jekyll SEO tag -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="layout">
|
||||
<a href="#menu" id="menuLink" class="menu-link">
|
||||
<span></span>
|
||||
</a>
|
||||
<div id="menu">
|
||||
<div class="pure-menu">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item">
|
||||
<div class="pure-menu-label">Versions:</div>
|
||||
</li>
|
||||
<li class="pure-menu-item version-0.9.0-draft.1 pure-menu-selected">
|
||||
<a href="/spec/0.9.0-draft.1.html" class="pure-menu-link">0.9.0-draft.1</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/parsecsv/csv-spec">
|
||||
<i class="fa fa-github" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="content">
|
||||
<h1 id="csv-spec-090-draft1">CSV Spec 0.9.0-draft.1</h1>
|
||||
<h2 id="summary">Summary</h2>
|
||||
<p>CSV is not a file format, it is a loose set of guidelines of how to structure
|
||||
tabular data into a plain text string. As such there’s an endless amount of
|
||||
<code class="highlighter-rouge">*.csv</code> files floating around which are highly incompatible with each other. The
|
||||
closest thing there is to a specification is <a href="http://tools.ietf.org/html/rfc4180">RFC
|
||||
4180</a>.</p>
|
||||
<h2 id="goals">Goals</h2>
|
||||
<p>This project is an attempt to summarize RFC 4180 and the information in the
|
||||
<a href="http://en.wikipedia.org/wiki/Comma-separated_values">Comma-separated values
|
||||
(CSV)</a> Wikipedia article
|
||||
into a easy to understand format. The spec will also take into account that the
|
||||
comma (<code class="highlighter-rouge">,</code>) character is not the only character used as a field
|
||||
delimiter. Semi-colons (<code class="highlighter-rouge">;</code>), tabs (<code class="highlighter-rouge">\t</code>), and more are popular field delimiter
|
||||
characters. As such the specification will more accurately be describing a
|
||||
CSV-like structured data format.</p>
|
||||
<p>We will also provide input/output test files that CSV parser/writer software
|
||||
libraries can use to validate if they properly adhere to the rules laid out in
|
||||
this specification. And if possible we will even try to provide code snippets in
|
||||
various languages that attempts to automatically determine the delimiter
|
||||
character used in any given input CSV-like formatted file/data.</p>
|
||||
<h2 id="roadmap">Roadmap</h2>
|
||||
<ol>
|
||||
<li>Write up core specification rules. <em>[in-progress]</em></li>
|
||||
<li>Create input/output test files covering all rules in the specification.</li>
|
||||
<li>Create website for <a href="http://csv-spec.org/">csv-spec.org</a>.</li>
|
||||
<li>Create linting tool as a NPM module, allowing easy validation of CSV data
|
||||
both client-side in a web browser, and server side via a command line tool.</li>
|
||||
<li>Create automatic delimiter character detection code snippets in various
|
||||
programming languages which CSV parser developers can freely use to enhance
|
||||
their libraries.</li>
|
||||
</ol>
|
||||
<h2 id="terminology">Terminology</h2>
|
||||
<ul>
|
||||
<li><strong>Field</strong> — A singular String value within a record.</li>
|
||||
<li><strong>Record</strong> (or <strong>Row</strong>) — A collection of fields. This is often referred to as
|
||||
a “line”, but a single record can span multiple text lines if a field within
|
||||
it contains one or more line breaks.</li>
|
||||
<li><strong>Delimiter</strong> — The character used to separate fields withing a row. Commonly
|
||||
this will be a comma (<code class="highlighter-rouge">,</code>), but semi-colons (<code class="highlighter-rouge">;</code>) or tabs (<code class="highlighter-rouge">\t</code>) are two other
|
||||
popular delimiter characters.</li>
|
||||
<li><strong>Header</strong> — The first row is often used to contain the column names for all
|
||||
remaining rows. Header names would be used as key names when CSV data is
|
||||
converted to JSON for example.</li>
|
||||
<li><strong>Line Break</strong> — Line breaks in CSV files can be CRLF (<code class="highlighter-rouge">\r\n</code>), LF (<code class="highlighter-rouge">\n</code>), and
|
||||
even in rare cases CR (<code class="highlighter-rouge">\r</code>).</li>
|
||||
<li><strong>LF, CR, and CRLF</strong> — Different types of line breaks, typically determined by
|
||||
the OS. Linux, OSX, and other *NIX operating systems generally use a line feed
|
||||
(LF or <code class="highlighter-rouge">\n</code>) character. Windows uses a carriage return (CR or <code class="highlighter-rouge">\r</code>) and a line
|
||||
feed character, effectively “CRLF” (<code class="highlighter-rouge">\r\n</code>).</li>
|
||||
</ul>
|
||||
<h2 id="csv-format-specification">CSV Format Specification</h2>
|
||||
<p>The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
|
||||
“SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be
|
||||
interpreted as described in <a href="https://tools.ietf.org/html/rfc2119">RFC 2119</a>.</p>
|
||||
<p>These rules are mostly based on the corresponding section from <a href="http://tools.ietf.org/html/rfc4180#section-2">RFC
|
||||
4180</a>, with minor changes,
|
||||
clarifications and improved examples.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Each record starts at the beginning of its own line, and ends with a line
|
||||
break (shown as <code class="highlighter-rouge">¬</code>).</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Though it is RECOMMENDED, the last record in a file is not required to have a
|
||||
ending line break.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>There may be an OPTIONAL header line appearing as the first line of the file
|
||||
with the same format as normal records. This header will contain names
|
||||
corresponding to the fields in the file, and MUST contain the same number of
|
||||
fields as the records in the rest of the file.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">field_1,field_2,field_3¬
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON (ignoring headers):</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"field_1"</span><span class="p">,</span><span class="w"> </span><span class="s2">"field_2"</span><span class="p">,</span><span class="w"> </span><span class="s2">"field_3"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
<p>JSON (using headers):</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="nt">"field_1"</span><span class="p">:</span><span class="w"> </span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_2"</span><span class="p">:</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">},</span><span class="w">
|
||||
</span><span class="p">{</span><span class="nt">"field_1"</span><span class="p">:</span><span class="w"> </span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_2"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="nt">"field_3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Within each record and the OPTIONAL header, there may be one or more fields,
|
||||
separated by a delimiter (normally a comma). Each record MUST contain the
|
||||
same number of fields throughout the file.</p>
|
||||
<p>CSV (invalid):</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
111,222,333,444¬
|
||||
xxx,yyy,zzz¬
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>The last field in a record MUST NOT be followed by a comma. This results in a
|
||||
additional field with nothing in it.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc,¬
|
||||
xxx,yyy,zzz,¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Spaces are considered part of a field and MUST NOT be ignored.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa , bbb , ccc¬
|
||||
xxx, yyy ,zzz ¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa "</span><span class="p">,</span><span class="w"> </span><span class="s2">" bbb "</span><span class="p">,</span><span class="w"> </span><span class="s2">" ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">" xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">" yyy "</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz "</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Fields containing line breaks (CRLF, LF, or CR), double quotes, or the
|
||||
delimiter character (normally a comma) MUST be enclosed in double-quotes.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,"b¬
|
||||
bb",ccc¬
|
||||
xxx,"y, yy",zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"b\r\nbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"y, yy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>A double-quote appearing inside a field MUST be escaped by preceding it with
|
||||
another double quote, and the field itself MUST be enclosed in double quotes.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,"b""bb",ccc¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"b\"bb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>When a field enclosed in double quotes has spaces before and/or after the
|
||||
double quotes, the spaces MUST be ignored, as the field starts and ends with
|
||||
the double quotes. However this is considered invalid formatting and the CSV
|
||||
parser SHOULD report some form of warning message.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">aaa,bbb,ccc¬
|
||||
xxx, "y, yy" ,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"y, yy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>It is possible to enclose every field in double quotes even if they don’t
|
||||
need to be enclosed. However it is RECOMMENDED to only enclose fields in
|
||||
double quotes that requires it.</p>
|
||||
<p>CSV:</p>
|
||||
<pre><code class="language-csv">"aaa","bbb","ccc"¬
|
||||
"xxx",yyy,zzz¬
|
||||
</code></pre>
|
||||
<p>JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"aaa"</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ccc"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"xxx"</span><span class="p">,</span><span class="w"> </span><span class="s2">"yyy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"zzz"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>All fields are always strings. CSV itself does not support type casting to
|
||||
integers, floats, booleans, or anything else. It is not a CSV library’s
|
||||
responsibility to type cast input CSV data.</p>
|
||||
<p>If type casting is required, it is up to the developer using a specific CSV
|
||||
library to ensure types are correctly dealt with.</p>
|
||||
<p>Input JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="mf">0.3</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="s2">"aaa"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="mi">11</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="mf">2.13</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
<p>Output CSV:</p>
|
||||
<pre><code class="language-csv">10,true,0.3,,aaa¬
|
||||
11,false,2.13,,bbb¬
|
||||
</code></pre>
|
||||
<p>Output CSV parsed back to JSON:</p>
|
||||
<div class="language-json highlighter-rouge">
|
||||
<pre class="highlight"><code><span class="p">[</span><span class="w"> </span><span class="p">[</span><span class="s2">"10"</span><span class="p">,</span><span class="w"> </span><span class="s2">"true"</span><span class="p">,</span><span class="w"> </span><span class="s2">"0.3"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="s2">"aaa"</span><span class="p">],</span><span class="w">
|
||||
</span><span class="p">[</span><span class="s2">"11"</span><span class="p">,</span><span class="w"> </span><span class="s2">"false"</span><span class="p">,</span><span class="w"> </span><span class="s2">"2.13"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="s2">"bbb"</span><span class="p">]</span><span class="w"> </span><span class="p">]</span><span class="w">
|
||||
</span></code></pre>
|
||||
</div>
|
||||
<p>At this point it is up to the developer themselves to type cast the above
|
||||
output data from the CSV parser.</p>
|
||||
</li>
|
||||
<li>However, when rendering type cast input data to CSV text, non-string types
|
||||
MUST be converted to a string in such a way that minimal information is
|
||||
lost.
|
||||
<ul>
|
||||
<li>Integers and floats MUST be rendered as a string version of themselves.</li>
|
||||
<li>Booleans <code class="highlighter-rouge">true</code> and <code class="highlighter-rouge">false</code> MUST be rendered as <code class="highlighter-rouge">true</code> and <code class="highlighter-rouge">false</code>
|
||||
strings, not as <code class="highlighter-rouge">1</code> or <code class="highlighter-rouge">0</code> numbers. If numbers are used the resulting
|
||||
CSV data is indistinguishable from actual integer numbers.</li>
|
||||
<li><code class="highlighter-rouge">Null</code>/<code class="highlighter-rouge">nil</code> values MUST be rendered as empty strings.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>When parsing input CSV data all forms of line breaks (CRLF, LF, and CR) MUST
|
||||
be supported.</li>
|
||||
<li>When rendering output CSV data, CRLF MUST be used for line breaks to ensure
|
||||
maximum cross-platform compatibility.</li>
|
||||
</ol>
|
||||
<h2 id="about">About</h2>
|
||||
<p>This CSV specification is authored by <a href="https://jimeh.me/">Jim Myhrberg</a>.</p>
|
||||
<p>If you’d like to leave feedback,
|
||||
please <a href="https://github.com/parsecsv/csv-spec/issues">open an issue on GitHub</a>.</p>
|
||||
<h2 id="license">License</h2>
|
||||
<p><a href="http://creativecommons.org/publicdomain/zero/1.0/">CC0 1.0 Universal</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/assets/main-870855580c69dec57be4c965d0cf8afe78afa6b7b6f6bdb5aff91ac0256c0a1a.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
312
index.md
Normal file
312
index.md
Normal file
@@ -0,0 +1,312 @@
|
||||
---
|
||||
title: CSV Spec 0.9.0-draft.1
|
||||
version: 0.9.0-draft.1
|
||||
---
|
||||
CSV Spec 0.9.0-draft.1
|
||||
====================
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
CSV is not a file format, it is a loose set of guidelines of how to structure
|
||||
tabular data into a plain text string. As such there's an endless amount of
|
||||
`*.csv` files floating around which are highly incompatible with each other. The
|
||||
closest thing there is to a specification is [RFC
|
||||
4180](http://tools.ietf.org/html/rfc4180).
|
||||
|
||||
Goals
|
||||
-----
|
||||
|
||||
This project is an attempt to summarize RFC 4180 and the information in the
|
||||
[Comma-separated values
|
||||
(CSV)](http://en.wikipedia.org/wiki/Comma-separated_values) Wikipedia article
|
||||
into a easy to understand format. The spec will also take into account that the
|
||||
comma (`,`) character is not the only character used as a field
|
||||
delimiter. Semi-colons (`;`), tabs (`\t`), and more are popular field delimiter
|
||||
characters. As such the specification will more accurately be describing a
|
||||
CSV-like structured data format.
|
||||
|
||||
We will also provide input/output test files that CSV parser/writer software
|
||||
libraries can use to validate if they properly adhere to the rules laid out in
|
||||
this specification. And if possible we will even try to provide code snippets in
|
||||
various languages that attempts to automatically determine the delimiter
|
||||
character used in any given input CSV-like formatted file/data.
|
||||
|
||||
Roadmap
|
||||
-------
|
||||
|
||||
1. Write up core specification rules. _[in-progress]_
|
||||
2. Create input/output test files covering all rules in the specification.
|
||||
3. Create website for [csv-spec.org](http://csv-spec.org/).
|
||||
4. Create linting tool as a NPM module, allowing easy validation of CSV data
|
||||
both client-side in a web browser, and server side via a command line tool.
|
||||
5. Create automatic delimiter character detection code snippets in various
|
||||
programming languages which CSV parser developers can freely use to enhance
|
||||
their libraries.
|
||||
|
||||
Terminology
|
||||
-----------
|
||||
|
||||
- **Field** — A singular String value within a record.
|
||||
- **Record** (or **Row**) — A collection of fields. This is often referred to as
|
||||
a "line", but a single record can span multiple text lines if a field within
|
||||
it contains one or more line breaks.
|
||||
- **Delimiter** — The character used to separate fields withing a row. Commonly
|
||||
this will be a comma (`,`), but semi-colons (`;`) or tabs (`\t`) are two other
|
||||
popular delimiter characters.
|
||||
- **Header** — The first row is often used to contain the column names for all
|
||||
remaining rows. Header names would be used as key names when CSV data is
|
||||
converted to JSON for example.
|
||||
- **Line Break** — Line breaks in CSV files can be CRLF (`\r\n`), LF (`\n`), and
|
||||
even in rare cases CR (`\r`).
|
||||
- **LF, CR, and CRLF** — Different types of line breaks, typically determined by
|
||||
the OS. Linux, OSX, and other *NIX operating systems generally use a line feed
|
||||
(LF or `\n`) character. Windows uses a carriage return (CR or `\r`) and a line
|
||||
feed character, effectively "CRLF" (`\r\n`).
|
||||
|
||||
CSV Format Specification
|
||||
------------------------
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||
interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
These rules are mostly based on the corresponding section from [RFC
|
||||
4180](http://tools.ietf.org/html/rfc4180#section-2), with minor changes,
|
||||
clarifications and improved examples.
|
||||
|
||||
1. Each record starts at the beginning of its own line, and ends with a line
|
||||
break (shown as `¬`).
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
2. Though it is RECOMMENDED, the last record in a file is not required to have a
|
||||
ending line break.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
3. There may be an OPTIONAL header line appearing as the first line of the file
|
||||
with the same format as normal records. This header will contain names
|
||||
corresponding to the fields in the file, and MUST contain the same number of
|
||||
fields as the records in the rest of the file.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
field_1,field_2,field_3¬
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
```
|
||||
|
||||
JSON (ignoring headers):
|
||||
|
||||
```json
|
||||
[ ["field_1", "field_2", "field_3"],
|
||||
["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
JSON (using headers):
|
||||
|
||||
```json
|
||||
[ {"field_1": "aaa", "field_2": "bbb", "field_3": "ccc"},
|
||||
{"field_1": "xxx", "field_2": "yyy", "field_3": "zzz"} ]
|
||||
```
|
||||
|
||||
4. Within each record and the OPTIONAL header, there may be one or more fields,
|
||||
separated by a delimiter (normally a comma). Each record MUST contain the
|
||||
same number of fields throughout the file.
|
||||
|
||||
CSV (invalid):
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
111,222,333,444¬
|
||||
xxx,yyy,zzz¬
|
||||
```
|
||||
|
||||
5. The last field in a record MUST NOT be followed by a comma. This results in a
|
||||
additional field with nothing in it.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc,¬
|
||||
xxx,yyy,zzz,¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc", ""],
|
||||
["xxx", "yyy", "zzz", ""] ]
|
||||
```
|
||||
|
||||
6. Spaces are considered part of a field and MUST NOT be ignored.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa , bbb , ccc¬
|
||||
xxx, yyy ,zzz ¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa ", " bbb ", " ccc"],
|
||||
[" xxx", " yyy ", "zzz "] ]
|
||||
```
|
||||
|
||||
7. Fields containing line breaks (CRLF, LF, or CR), double quotes, or the
|
||||
delimiter character (normally a comma) MUST be enclosed in double-quotes.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,"b¬
|
||||
bb",ccc¬
|
||||
xxx,"y, yy",zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "b\r\nbb", "ccc"],
|
||||
["xxx", "y, yy", "zzz"] ]
|
||||
```
|
||||
|
||||
8. A double-quote appearing inside a field MUST be escaped by preceding it with
|
||||
another double quote, and the field itself MUST be enclosed in double quotes.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,"b""bb",ccc¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "b\"bb", "ccc"] ]
|
||||
```
|
||||
|
||||
9. When a field enclosed in double quotes has spaces before and/or after the
|
||||
double quotes, the spaces MUST be ignored, as the field starts and ends with
|
||||
the double quotes. However this is considered invalid formatting and the CSV
|
||||
parser SHOULD report some form of warning message.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
xxx, "y, yy" ,zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "y, yy", "zzz"] ]
|
||||
```
|
||||
|
||||
10. It is possible to enclose every field in double quotes even if they don't
|
||||
need to be enclosed. However it is RECOMMENDED to only enclose fields in
|
||||
double quotes that requires it.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
"aaa","bbb","ccc"¬
|
||||
"xxx",yyy,zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
11. All fields are always strings. CSV itself does not support type casting to
|
||||
integers, floats, booleans, or anything else. It is not a CSV library's
|
||||
responsibility to type cast input CSV data.
|
||||
|
||||
If type casting is required, it is up to the developer using a specific CSV
|
||||
library to ensure types are correctly dealt with.
|
||||
|
||||
Input JSON:
|
||||
|
||||
```json
|
||||
[ [10, true, 0.3, null, "aaa"],
|
||||
[11, false, 2.13, "", "bbb"] ]
|
||||
```
|
||||
|
||||
Output CSV:
|
||||
|
||||
```csv
|
||||
10,true,0.3,,aaa¬
|
||||
11,false,2.13,,bbb¬
|
||||
```
|
||||
|
||||
Output CSV parsed back to JSON:
|
||||
|
||||
```json
|
||||
[ ["10", "true", "0.3", "", "aaa"],
|
||||
["11", "false", "2.13", "", "bbb"] ]
|
||||
```
|
||||
|
||||
At this point it is up to the developer themselves to type cast the above
|
||||
output data from the CSV parser.
|
||||
|
||||
12. However, when rendering type cast input data to CSV text, non-string types
|
||||
MUST be converted to a string in such a way that minimal information is
|
||||
lost.
|
||||
- Integers and floats MUST be rendered as a string version of themselves.
|
||||
- Booleans `true` and `false` MUST be rendered as `true` and `false`
|
||||
strings, not as `1` or `0` numbers. If numbers are used the resulting
|
||||
CSV data is indistinguishable from actual integer numbers.
|
||||
- `Null`/`nil` values MUST be rendered as empty strings.
|
||||
|
||||
13. When parsing input CSV data all forms of line breaks (CRLF, LF, and CR) MUST
|
||||
be supported.
|
||||
14. When rendering output CSV data, CRLF MUST be used for line breaks to ensure
|
||||
maximum cross-platform compatibility.
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
This CSV specification is authored by [Jim Myhrberg](https://jimeh.me/).
|
||||
|
||||
If you'd like to leave feedback,
|
||||
please [open an issue on GitHub](https://github.com/parsecsv/csv-spec/issues).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
[CC0 1.0 Universal](http://creativecommons.org/publicdomain/zero/1.0/)
|
||||
|
||||
312
spec/0.9.0-draft.1.md
Normal file
312
spec/0.9.0-draft.1.md
Normal file
@@ -0,0 +1,312 @@
|
||||
---
|
||||
title: CSV Spec 0.9.0-draft.1
|
||||
version: 0.9.0-draft.1
|
||||
---
|
||||
CSV Spec 0.9.0-draft.1
|
||||
====================
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
CSV is not a file format, it is a loose set of guidelines of how to structure
|
||||
tabular data into a plain text string. As such there's an endless amount of
|
||||
`*.csv` files floating around which are highly incompatible with each other. The
|
||||
closest thing there is to a specification is [RFC
|
||||
4180](http://tools.ietf.org/html/rfc4180).
|
||||
|
||||
Goals
|
||||
-----
|
||||
|
||||
This project is an attempt to summarize RFC 4180 and the information in the
|
||||
[Comma-separated values
|
||||
(CSV)](http://en.wikipedia.org/wiki/Comma-separated_values) Wikipedia article
|
||||
into a easy to understand format. The spec will also take into account that the
|
||||
comma (`,`) character is not the only character used as a field
|
||||
delimiter. Semi-colons (`;`), tabs (`\t`), and more are popular field delimiter
|
||||
characters. As such the specification will more accurately be describing a
|
||||
CSV-like structured data format.
|
||||
|
||||
We will also provide input/output test files that CSV parser/writer software
|
||||
libraries can use to validate if they properly adhere to the rules laid out in
|
||||
this specification. And if possible we will even try to provide code snippets in
|
||||
various languages that attempts to automatically determine the delimiter
|
||||
character used in any given input CSV-like formatted file/data.
|
||||
|
||||
Roadmap
|
||||
-------
|
||||
|
||||
1. Write up core specification rules. _[in-progress]_
|
||||
2. Create input/output test files covering all rules in the specification.
|
||||
3. Create website for [csv-spec.org](http://csv-spec.org/).
|
||||
4. Create linting tool as a NPM module, allowing easy validation of CSV data
|
||||
both client-side in a web browser, and server side via a command line tool.
|
||||
5. Create automatic delimiter character detection code snippets in various
|
||||
programming languages which CSV parser developers can freely use to enhance
|
||||
their libraries.
|
||||
|
||||
Terminology
|
||||
-----------
|
||||
|
||||
- **Field** — A singular String value within a record.
|
||||
- **Record** (or **Row**) — A collection of fields. This is often referred to as
|
||||
a "line", but a single record can span multiple text lines if a field within
|
||||
it contains one or more line breaks.
|
||||
- **Delimiter** — The character used to separate fields withing a row. Commonly
|
||||
this will be a comma (`,`), but semi-colons (`;`) or tabs (`\t`) are two other
|
||||
popular delimiter characters.
|
||||
- **Header** — The first row is often used to contain the column names for all
|
||||
remaining rows. Header names would be used as key names when CSV data is
|
||||
converted to JSON for example.
|
||||
- **Line Break** — Line breaks in CSV files can be CRLF (`\r\n`), LF (`\n`), and
|
||||
even in rare cases CR (`\r`).
|
||||
- **LF, CR, and CRLF** — Different types of line breaks, typically determined by
|
||||
the OS. Linux, OSX, and other *NIX operating systems generally use a line feed
|
||||
(LF or `\n`) character. Windows uses a carriage return (CR or `\r`) and a line
|
||||
feed character, effectively "CRLF" (`\r\n`).
|
||||
|
||||
CSV Format Specification
|
||||
------------------------
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||
interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
These rules are mostly based on the corresponding section from [RFC
|
||||
4180](http://tools.ietf.org/html/rfc4180#section-2), with minor changes,
|
||||
clarifications and improved examples.
|
||||
|
||||
1. Each record starts at the beginning of its own line, and ends with a line
|
||||
break (shown as `¬`).
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
2. Though it is RECOMMENDED, the last record in a file is not required to have a
|
||||
ending line break.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
3. There may be an OPTIONAL header line appearing as the first line of the file
|
||||
with the same format as normal records. This header will contain names
|
||||
corresponding to the fields in the file, and MUST contain the same number of
|
||||
fields as the records in the rest of the file.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
field_1,field_2,field_3¬
|
||||
aaa,bbb,ccc¬
|
||||
xxx,yyy,zzz¬
|
||||
```
|
||||
|
||||
JSON (ignoring headers):
|
||||
|
||||
```json
|
||||
[ ["field_1", "field_2", "field_3"],
|
||||
["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
JSON (using headers):
|
||||
|
||||
```json
|
||||
[ {"field_1": "aaa", "field_2": "bbb", "field_3": "ccc"},
|
||||
{"field_1": "xxx", "field_2": "yyy", "field_3": "zzz"} ]
|
||||
```
|
||||
|
||||
4. Within each record and the OPTIONAL header, there may be one or more fields,
|
||||
separated by a delimiter (normally a comma). Each record MUST contain the
|
||||
same number of fields throughout the file.
|
||||
|
||||
CSV (invalid):
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
111,222,333,444¬
|
||||
xxx,yyy,zzz¬
|
||||
```
|
||||
|
||||
5. The last field in a record MUST NOT be followed by a comma. This results in a
|
||||
additional field with nothing in it.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc,¬
|
||||
xxx,yyy,zzz,¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc", ""],
|
||||
["xxx", "yyy", "zzz", ""] ]
|
||||
```
|
||||
|
||||
6. Spaces are considered part of a field and MUST NOT be ignored.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa , bbb , ccc¬
|
||||
xxx, yyy ,zzz ¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa ", " bbb ", " ccc"],
|
||||
[" xxx", " yyy ", "zzz "] ]
|
||||
```
|
||||
|
||||
7. Fields containing line breaks (CRLF, LF, or CR), double quotes, or the
|
||||
delimiter character (normally a comma) MUST be enclosed in double-quotes.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,"b¬
|
||||
bb",ccc¬
|
||||
xxx,"y, yy",zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "b\r\nbb", "ccc"],
|
||||
["xxx", "y, yy", "zzz"] ]
|
||||
```
|
||||
|
||||
8. A double-quote appearing inside a field MUST be escaped by preceding it with
|
||||
another double quote, and the field itself MUST be enclosed in double quotes.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,"b""bb",ccc¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "b\"bb", "ccc"] ]
|
||||
```
|
||||
|
||||
9. When a field enclosed in double quotes has spaces before and/or after the
|
||||
double quotes, the spaces MUST be ignored, as the field starts and ends with
|
||||
the double quotes. However this is considered invalid formatting and the CSV
|
||||
parser SHOULD report some form of warning message.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
aaa,bbb,ccc¬
|
||||
xxx, "y, yy" ,zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "y, yy", "zzz"] ]
|
||||
```
|
||||
|
||||
10. It is possible to enclose every field in double quotes even if they don't
|
||||
need to be enclosed. However it is RECOMMENDED to only enclose fields in
|
||||
double quotes that requires it.
|
||||
|
||||
CSV:
|
||||
|
||||
```csv
|
||||
"aaa","bbb","ccc"¬
|
||||
"xxx",yyy,zzz¬
|
||||
```
|
||||
|
||||
JSON:
|
||||
|
||||
```json
|
||||
[ ["aaa", "bbb", "ccc"],
|
||||
["xxx", "yyy", "zzz"] ]
|
||||
```
|
||||
|
||||
11. All fields are always strings. CSV itself does not support type casting to
|
||||
integers, floats, booleans, or anything else. It is not a CSV library's
|
||||
responsibility to type cast input CSV data.
|
||||
|
||||
If type casting is required, it is up to the developer using a specific CSV
|
||||
library to ensure types are correctly dealt with.
|
||||
|
||||
Input JSON:
|
||||
|
||||
```json
|
||||
[ [10, true, 0.3, null, "aaa"],
|
||||
[11, false, 2.13, "", "bbb"] ]
|
||||
```
|
||||
|
||||
Output CSV:
|
||||
|
||||
```csv
|
||||
10,true,0.3,,aaa¬
|
||||
11,false,2.13,,bbb¬
|
||||
```
|
||||
|
||||
Output CSV parsed back to JSON:
|
||||
|
||||
```json
|
||||
[ ["10", "true", "0.3", "", "aaa"],
|
||||
["11", "false", "2.13", "", "bbb"] ]
|
||||
```
|
||||
|
||||
At this point it is up to the developer themselves to type cast the above
|
||||
output data from the CSV parser.
|
||||
|
||||
12. However, when rendering type cast input data to CSV text, non-string types
|
||||
MUST be converted to a string in such a way that minimal information is
|
||||
lost.
|
||||
- Integers and floats MUST be rendered as a string version of themselves.
|
||||
- Booleans `true` and `false` MUST be rendered as `true` and `false`
|
||||
strings, not as `1` or `0` numbers. If numbers are used the resulting
|
||||
CSV data is indistinguishable from actual integer numbers.
|
||||
- `Null`/`nil` values MUST be rendered as empty strings.
|
||||
|
||||
13. When parsing input CSV data all forms of line breaks (CRLF, LF, and CR) MUST
|
||||
be supported.
|
||||
14. When rendering output CSV data, CRLF MUST be used for line breaks to ensure
|
||||
maximum cross-platform compatibility.
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
This CSV specification is authored by [Jim Myhrberg](https://jimeh.me/).
|
||||
|
||||
If you'd like to leave feedback,
|
||||
please [open an issue on GitHub](https://github.com/parsecsv/csv-spec/issues).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
[CC0 1.0 Universal](http://creativecommons.org/publicdomain/zero/1.0/)
|
||||
|
||||
Reference in New Issue
Block a user