Commit 6014b2c2 authored by Zéfling's avatar Zéfling 🎨
Browse files

more options for maxLength

parent 8cdc2f01
......@@ -4,6 +4,7 @@
- Add option `wrapAttrNumber`
- Add options `prettier` on `attrPosition`
- Add options `maxLength` for text and `attrPosition` (`inline *`)
## V0.1.0 (2022-02-10)
......
MIT License
Copyright (c) 2020 Célian Veyssière (aka Zéfling)
Copyright (c) 2020-2022 Célian Veyssière (aka Zéfling)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -13,6 +13,7 @@
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"publish": "npm run publish dist/json2html",
"build:lib": "ng build json2html --configuration production && cp *.md dist/json2html",
"build:demo": "ng build --configuration production"
},
......
......@@ -35,12 +35,23 @@ export interface Json2htmlOptions {
/**
* attribute alignment:
* * `inline`: no alignment
* * `inline space`: wrap with alignment with higher level
* * `inline alignTag`: wrap with alignment with the tag
* * `inline alignFirstAttr`: wrap alignment with the first attribute
* * `space`: alignment with higher level
* * `alignTag`: alignment with the tag
* * `alignFirstAttr`: alignment with the first attribute
* * `prettier`: like Prettier formatter
*/
attrPosition?: 'inline' | 'space' | 'alignTag' | 'alignFirstAttr' | 'prettier';
attrPosition?:
| 'inline'
| 'inline space'
| 'inline alignTag'
| 'inline alignFirstAttr'
| 'space'
| 'alignTag'
| 'alignFirstAttr'
| 'prettier';
/** attr number wen 0 == 'inline' */
wrapAttrNumber?: number;
/** Format of the targeted structure */
......@@ -136,6 +147,7 @@ export class Json2html {
* generation in string for a node (tag with attributes and content)
* @param lvl node level
* @param json node data
* @param inline force inline
* @returns render of node
*/
private _generate(lvl: number, json: Json2htmlRef, inline: boolean = false): string {
......@@ -163,6 +175,7 @@ export class Json2html {
* attributes list generation
* @param lvl level node
* @param json node data
* @param inline force inline
* @returns attributes tag
*/
private _generateAttrs(lvl: number, json: Json2htmlRef, inline: boolean) {
......@@ -172,25 +185,46 @@ export class Json2html {
const length = Object.values(json.attrs).filter(i => i !== undefined).length;
const typeAlign =
(this.options.wrapAttrNumber ?? 1) < length && !inline ? this.options.attrPosition : 'inline';
let attrLine = `${this._getSpacing(lvl, 1)}${json.tag} `;
let attrLine = `${this._getSpacing(lvl, 1)}${json.tag}`;
let count = 1;
for (const id in attrs) {
if (attrs[id] !== undefined) {
const attrCurrent = `${id}${attrs[id] !== null || attrs[id] ? `="${attrs[id]}"` : ''}`;
Object.keys(attrs).forEach((id, index, array) => {
const value = attrs[id];
if (value !== undefined) {
const attrCurrent = `${id}${value !== null || value ? `="${value}"` : ''}`;
let attr = '';
let attrAdd = '';
const [align, type] = typeAlign.split(' ');
switch (typeAlign) {
switch (align) {
case 'inline':
if (
!this.options.maxLength ||
(attrLine + ' ' + attrCurrent).length <= this.options.maxLength
(
attrLine.replace('\n', '') +
(count > 1 ? ' ' : '') +
attrCurrent +
(index === array.length - 1 ? '>' : '')
).length < this.options.maxLength ||
type === undefined
) {
attrAdd = ' ';
count++;
} else {
attrAdd = `\n${this._getSpacing(lvl + 1)}`;
attrLine = this._getSpacing(lvl);
switch (type) {
case 'space':
attrAdd = `\n${this._getSpacing(lvl + 1)}`;
break;
case 'alignTag':
attrAdd = `\n${this._getSpacing(lvl, 1)}`;
break;
case 'alignFirstAttr':
attrAdd = `\n${this._getSpacing(lvl, json.tag.length + 2)}`;
break;
}
attrLine = '';
count = 1;
}
break;
case 'space':
......@@ -220,7 +254,7 @@ export class Json2html {
attrLine += attr;
string += attr;
}
}
});
switch (typeAlign) {
case 'prettier':
......@@ -235,6 +269,7 @@ export class Json2html {
* tag body generation
* @param lvl level node
* @param json node data
* @param inline force inline
* @returns render of body
*/
private _generateBody(lvl: number, json: Json2htmlRef, inline: boolean) {
......@@ -256,6 +291,7 @@ export class Json2html {
* @param lvl level node
* @param element node data or string
* @param onlyOne body this an unique node
* @param inline force inline
* @returns render of body
*/
private _generateBodyElement(
......@@ -277,10 +313,46 @@ export class Json2html {
};
}
string += typeof element === 'string' ? element : this._generate(lvl + 1, element, inline);
string +=
typeof element === 'string'
? this._formatText(lvl + 1, element, inline)
: this._generate(lvl + 1, element, inline);
return string;
}
/**
* formated string
* @param lvl level node
* @param string text
* @param inline inline
* @returns render of string
*/
private _formatText(lvl: number, string: string, inline: boolean = false): string {
let formatedText = '';
const space = this._getSpacing(lvl);
if (!inline && this.options.maxLength) {
const list = string.split('\n');
for (const line of list) {
if ((space + line).length > this.options.maxLength) {
const frags = line.split(' ');
let lineBuild = '';
for (const frag of frags) {
if ((space + lineBuild + (lineBuild ? ' ' : '') + frag).length < this.options.maxLength) {
lineBuild += (lineBuild ? ' ' : '') + frag;
} else {
formatedText += (formatedText ? '\n' + space : '') + lineBuild;
lineBuild = frag;
}
}
formatedText += (formatedText ? '\n' + space : '') + lineBuild;
} else {
formatedText += (formatedText ? '\n' + space : '') + line;
}
}
}
return formatedText || string;
}
/**
* if multiline rendering
*/
......
......@@ -56,6 +56,11 @@
<span>attrPosition</span>
<select [value]="attrPosition" (change)="attrPosition = $event.target.value; generated()">
<option value="inline">inline: no alignment</option>
<option value="inline space">inline space: wrap with alignment with higher level</option>
<option value="inline alignTag">inline alignTag: wrap with alignment with the tag</option>
<option value="inline alignFirstAttr">
inline alignFirstAttr: wrap alignment with the first attribute
</option>
<option value="space">space: alignment with higher level</option>
<option value="alignTag">alignTag: alignment with the tag</option>
<option value="alignFirstAttr">alignFirstAttr (default): alignment with the first attribute</option>
......
::ng-deep {
:root {
}
body {
font-family: sans;
}
* {
box-sizing: border-box;
}
}
main {
display: grid;
grid-template: 'a b c' / 2fr 2fr 2fr;
......
......@@ -19,10 +19,9 @@ export class AppComponent {
spaceType: 'space' | 'tab' = 'space';
spaceLength = 4;
spaceBase = 0;
// maxLenght= 0;
attrPosition: 'inline' | 'space' | 'alignTag' | 'alignFirstAttr' = 'alignFirstAttr';
wrapAttrNumber = 1;
maxLength = 0;
maxLength = 80;
type: 'html' | 'xml' = 'html';
formatting: 'inline' | 'multiline' = 'multiline';
indent = true;
......
......@@ -24,8 +24,24 @@ export const examples = [
'test2',
{
tag: 'div',
attrs: { id: 'test-subdiv', class: 'foobar' },
body: 'test3',
attrs: {
id: 'test-subdiv',
class: 'foobar',
style: 'all: initial;',
lang: 'ja',
'data-test1': 'value1',
'data-test2': 'value2',
'data-test3': 'value3',
},
body:
`Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem ` +
`Ipsum has been the industry's standard dummy text ever since the 1500s, ` +
`when an unknown printer took a galley of type and scrambled it to make a type ` +
`specimen book. It has survived not only five centuries, but also the leap into ` +
`electronic typesetting, remaining essentially unchanged. It was popularised in the ` +
`1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more ` +
`recently with desktop publishing software like Aldus PageMaker including versions ` +
`of Lorem Ipsum.`,
},
],
},
......
/* You can add global styles to this file, and also import other style files */
body {
font-family: sans;
}
* {
box-sizing: border-box;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment