Skip to content

Commit

Permalink
Implemented stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
IHateYourCode committed Jul 23, 2022
1 parent 682ff59 commit 105d3f6
Show file tree
Hide file tree
Showing 5 changed files with 313 additions and 8 deletions.
41 changes: 35 additions & 6 deletions Source/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@

# HJSON   [![Badge License]][License]

*A parser / stringifier for **[HJSON]**.*
A parser / stringifier for **[HJSON]**.

<br>

## Import

```JavaScript
```js
import HJson from 'https://deno.land/x/hjson/mod.ts'
```

<br>
<br>

## Parsing
## Parse

```JavaScript
```js
import { parse } from 'https://deno.land/x/hjson/mod.ts'

const { log } = console;
Expand Down Expand Up @@ -48,9 +48,38 @@ log(parse(hjson));
<br>
<br>

## Stringification
## Stringify

**Work In Progress**
```js
import { stringify } from 'https://deno.land/x/hjson/mod.ts'

const { log } = console;

const object = {
some : 3 ,
variables : [ 'with' , 'a' , 'lot' ] ,
inside : { them : 9 }
}

log(stringify(hjson));


/*
* {
* some : 3
*
* variables : [
* with
* a
* lot
* ]
*
* inside : {
* them : 9
* }
* }
*/
```

<br>

Expand Down
228 changes: 228 additions & 0 deletions Source/Stringify/Encode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@


export default function stringify(object,options = {}){

options.style ??= 'modern';

if(options.style !== 'modern')
throw 'Unsupported style';

const base = modern(object);

const pretty = base
.replace(/\[\s+\{/g,'[{')
.replace(/\}\s+\]/g,'}]')
.replace(/\}\s*,\s*\{/g,'},{');
// .replace(//g,`\n$1:\n\n'''`);
// .replace(/\[\{\s*/g,'[{\n\n');

return [... indent(pretty) ].join('\n');
}

function * indent(pretty){

const lines = pretty.split('\n');

let level = 0;
let padding = ' ';
let open = false;


for(const line of lines){

const padded = () =>
padding.repeat(Math.max(level,0)) + line;

const trimmed = line.trim();

if(trimmed.length < 1){
yield padded();
continue;
}

if(trimmed.startsWith(`'''`)){

if(!open)
level++

yield padded();

if(open)
level--;

open = !open;
continue;
}

if(
trimmed.startsWith('{') ||
trimmed.endsWith('{') ||
trimmed.endsWith('[')
){
yield padded();
level++;
continue;
}

if(
trimmed.startsWith('}') ||
trimmed.endsWith('}') ||
trimmed.endsWith(']')
){
level--;
yield padded();
continue;
}

yield padded();
}
}


function modern(object){

let lines = toObject(object);

return lines.join('\n');
}

function toItem(item){

switch(typeof item){
case 'number' :
return [ `${ item }` ];
case 'boolean' :
return [ (item) ? 'true' : 'false' ];
case 'string' :

if(item.includes('\n'))
return [ `'''` , item , `'''` ];

if(
item.startsWith('#') ||
/[,:\[\]\{\}]/g.test(item)
) return [ `'${ item }'`];

return [ `${ item }` ];
case 'array' :
return toArray(item);
case 'object':
return toObject(item);
}
}
//
// function indent(string){
// return ' ' + string;
// }

function toArray(array){

const lines = [ '[' ];

for(const item of array)
lines.push(...toItem(item));//.map(indent)

lines.push(']');

return (lines.length === 2)
? [ '[]' ]
: lines ;
}

function toObject(object){

const longestFirst = ([ a ],[ b ]) => b.length - a.length;

const
entries = Object.entries(object) ,
simple = entries
.filter(([ _ , value ]) => [ 'string' , 'number' , 'boolean' ].includes(typeof value))
.sort(longestFirst)
.map(formString)
.flat();
// .map((string) => ' ' + string);

const complex = entries
.filter(([ _ , value ]) => [ 'object' , 'array' ].includes(typeof value))
.sort(longestFirst)
.map(toComplex)
.flat();
// .map((string) => ' ' + string);

complex.shift();

const lines = [ '{' ];

if(simple.length && complex.length)
lines.push('');

if(simple.length)
lines.push(...simple);

if(simple.length && complex.length)
lines.push('');

if(complex.length)
lines.push(...complex);

lines.push('}');

return (lines.length === 2)
? [ '{}' ]
: lines ;
}

function toComplex([ key , value ]){

if(Array.isArray(value)){

const [ first , ...rest ] = toArray(value);

return [
'' ,
`${ toString(key) } : ${ first }`,
...rest
];
} else {
const [ first , ...rest ] = toObject(value);

return [
'' ,
`${ toString(key) } : ${ first }`,
...rest
];
}
}


function formString([ key , value ]){
switch(typeof value){
case 'number' :
return [ `${ toString(key) } : ${ value }` ];
case 'boolean' :
return [ `${ toString(key) } : ${ (value)
? ['true']
: ['false'] }` ]
case 'string' :

if(value.includes('\n'))
return [ '' , `${ toString(key) }:` , '' , `'''` , value , `'''` ];

if(
value.startsWith('#') ||
/[,:\[\]\{\}]/g.test(value)
) return [ `${ toString(key) } : '${ value }'`];

return [ `${ toString(key) } : ${ value }` ];
}
}

function toString(value){

if(
value.startsWith('#') ||
/[,:\[\]\{\}]/g.test(value)
) return `'${ value }'`;

return value;
}
7 changes: 7 additions & 0 deletions Source/Stringify/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

import encode from './Encode.js'


export default function stringify ( value : object , options : object ) : string {
return encode(value,options);
}
11 changes: 9 additions & 2 deletions Source/mod.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@

import decode from './Decode.js'


export function parse ( text : string ) : object {
return decode(text);
}

export default { parse }

import encode from './Stringify/mod.ts'

export function stringify ( value : object , options : object ) : string {
return encode(value,options);
}


export default { parse , stringify }
34 changes: 34 additions & 0 deletions Tests/Stringify/Basic.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

import { stringify } from '../../Source/mod.ts'

const { log } = console;


const object = {
difficulty : 3 ,
name : 'lab' ,
planet : 'pluto' ,
sector : 3 ,
captureWave : 10 ,

research : {

name : '\ntesting \'wow\'\n' ,

parent : 'nuclearFacility' ,

objectives: [{
preset : 'nuclearFacility' ,
type : 'SectorComplete'
}]
}
}



Deno.test('Basic Stringification Test',() => {

const hjson = stringify(object);

log(hjson);
});

0 comments on commit 105d3f6

Please sign in to comment.