Skip to content

Commit

Permalink
New version of CSVLint.io
Browse files Browse the repository at this point in the history
  • Loading branch information
davetaz committed Nov 7, 2024
0 parents commit 76a0bac
Show file tree
Hide file tree
Showing 34 changed files with 9,255 additions and 0 deletions.
492 changes: 492 additions & 0 deletions index.js

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"errors": {
"missing_value": "This field is required but is missing.",
"min_length": "This field does not meet the minimum length requirement.",
"max_length": "This field exceeds the maximum length allowed.",
"pattern": "The value does not match the required pattern.",
"unique": "This field must be unique, but a duplicate value was found.",
"invalid_type": "The value is not of the expected type.",
"below_minimum": "The value is below the minimum allowed.",
"above_maximum": "The value is above the maximum allowed.",
"invalid_enum_value": "The value is not one of the allowed options.",
"invalid_regex": "The provided regular expression pattern is invalid.",
"wrong_content_type": "The content type is not 'text/csv'.",
"ragged_rows": "Row has a different number of columns than the first row.",
"blank_rows": "The row is completely empty.",
"invalid_encoding": "Encoding error when parsing row due to invalid characters.",
"not_found": "HTTP 404 error when retrieving the data.",
"stray_quote": "There is a missing or stray quote in the row.",
"unclosed_quote": "There is an unclosed quoted field in the row.",
"whitespace": "A quoted column has leading or trailing whitespace.",
"line_breaks": "Line breaks were inconsistent or incorrectly specified."
},
"warnings": {
"malformed_header": "The header row does not match the expected structure.",
"missing_column": "A column is missing from this row.",
"extra_column": "There is an extra column in this row.",
"no_encoding": "The Content-Type header does not have a charset parameter.",
"encoding": "The character set is not UTF-8.",
"no_content_type": "The file is being served without a Content-Type header.",
"excel": "The file extension is .xls and lacks a Content-Type header.",
"check_options": "The CSV file appears to contain only a single column.",
"inconsistent_values": "Inconsistent values in the same column.",
"empty_column_name": "A column in the CSV header has an empty name.",
"duplicate_column_name": "A column in the CSV header has a duplicate name.",
"title_row": "There appears to be a title field in the first row of the CSV."
},
"info": {
"assumed_header": "A header row is assumed to be present based on the file format.",
"nonrfc_line_breaks": "The file uses non-standard line breaks, which may cause compatibility issues."
}
}
33 changes: 33 additions & 0 deletions models/ValidationReport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const mongoose = require('mongoose');

const validationEntrySchema = new mongoose.Schema(
{
type: { type: String },
category: { type: String },
row: { type: Number, default: null },
column: { type: Number, default: null }
},
{ _id: false } // Prevent _id generation for each entry
);

const validationReportSchema = new mongoose.Schema(
{
version: { type: String },
licence: { type: String },
hash: { type: String, unique: true },
validationCount: { type: Number, default: 1 }, // Initialize validationCount
validation: {
sourcePresent: { type: Boolean },
schemaPresent: { type: Boolean },
valid: { type: Boolean },
errors: [validationEntrySchema],
warnings: [validationEntrySchema],
info: [validationEntrySchema]
}
},
{
timestamps: { createdAt: 'createdAt', updatedAt: 'lastModified' }
}
);

module.exports = mongoose.model('ValidationReport', validationReportSchema);
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "csvlint-client",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.7.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"ejs": "^3.1.10",
"express": "^4.21.1",
"form-data": "^4.0.1",
"mongoose": "^8.8.0",
"multer": "^1.4.5-lts.1"
}
}
229 changes: 229 additions & 0 deletions public/css/csvlint.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
section {
max-width: 1400px;
margin-left: auto;
margin-right: auto;
}
.siteTitle {
display: block;
color: white;
font-size: 2.5em;
}
.subtitle {
font-size: 1.1em;
}
/* 50:50 content wrapper */
.content-wrapper {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
input.file {
background: transparent;
}

/* Text section styling */
.text {
flex: 1;
min-width: 280px;
}

/* Validation box styling */
.validation-box {
flex: 1;
min-width: 280px;
max-width: 550px;
padding: 20px;
border: none;
border-radius: 0;
background-color: var(--color-light-grey);

}
.validation-box h2 {
margin-top: 0em;
}
.validation-box button {
margin-top: 1em;
width: 100%;
}
.validation-box button:hover {
background-color: white;
}
.validation-box .btn:hover{
background: white;
}
.validation-box .main-label {
color: var(--color-dark-blue);
font-size: 1.2em;
font-weight: 200;
}
.validation-box .file-name {
display: inline-block;
margin-left: 10px;
font-size: 1em;
color: #555;
font-style: italic;
}
/* Dialect Options Collapsible Styling */
.toggle-dialect-btn {
width: 100%;
}
.or-divider {
display: none;
padding-left: 0.5em;
margin-bottom: 1em;
}
input.url {
width: 95%;
height: 1.2em;
font-size: 1.2em;
}
.file-input {
display: none;
}


#dialectOptions {
overflow: hidden;
transition: max-height 0.3s ease;
}

#dialectOptions.collapsed {
max-height: 0;
padding: 0;
opacity: 0;
visibility: hidden;
}
#dialectOptions:not(.collapsed) {
max-height: 1000px; /* Large max-height to allow for content expansion */
opacity: 1;
visibility: visible;
padding: 10px 0;
}
@media (max-width: 768px) {
.content-wrapper {
flex-direction: column;
}

.validation-box {
margin-top: 20px;
}
}
.dialect-option {
display: table;
}
.dialect-option label {
display: table-cell;
min-width: 12em;
vertical-align: middle;
}
.dialect-option input, .dialect-option select {
display: table-cell;
border: 1px solid var(--color-light-grey);
border-radius: 0px;
}
h1 {
}

h2 {
margin-top: 20px;
}

.csv-status {
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
font-weight: bold;
font-size: 1.2em;
}

.csv-status.valid {
color: #2e7d32;
background-color: #e8f5e9;
border-left: 5px solid #2e7d32;
}

.csv-status.invalid {
color: #c62828;
background-color: #ffebee;
border-left: 5px solid #c62828;
}

/* Summary Table */
.summary-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}

.summary-table th,
.summary-table td {
padding: 10px;
text-align: left;
border: 1px solid #ddd;
}

.summary-table th {
background-color: #f4f4f4;
font-weight: bold;
}

.summary-table tbody tr:nth-child(1) td {
color: #e74c3c;
font-weight: bold;
}

.summary-table tbody tr:nth-child(2) td {
color: #f39c12;
font-weight: bold;
}

.summary-table tbody tr:nth-child(3) td {
color: #3498db;
font-weight: bold;
}

/* Message Box Styling */
.message-box {
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 15px;
padding: 15px;
background-color: #f9f9f9;
}

.message-box.Error {
border-left: 5px solid #e74c3c;
background-color: #fce4e4;
}

.message-box.Warning {
border-left: 5px solid #f39c12;
background-color: #fef7e1;
}

.message-box.Info {
border-left: 5px solid #3498db;
background-color: #eaf4fb;
}

.message-header {
font-weight: bold;
font-size: 1.1em;
margin-bottom: 10px;
}

.message-category {
text-transform: uppercase;
}

.message-content p {
margin: 5px 0;
}

pre {
background-color: #333;
color: #f4f4f4;
padding: 10px;
border-radius: 3px;
overflow-x: auto;
}
Loading

0 comments on commit 76a0bac

Please sign in to comment.