Commit 204dbd6b authored by Zéfling's avatar Zéfling 🎨
Browse files

Add prettier for attrPosition

- add wrapAttrNumber
- prettier code formating
parent b38f7293
# Add files here to ignore them from prettier formatting
{
"singleQuote": true,
"semi": true,
"tabWidth": 4,
"printWidth": 120,
"arrowParens": "avoid",
"trailingComma": "all",
"bracketSpacing": true,
"overrides": [
{
"files": "*.json",
"options": {
"tabWidth": 2
}
}
]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "pwa-chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"tsImportSorter.configuration.emptyLinesAfterAllImports": 2,
"tsImportSorter.configuration.emptyLinesBetweenGroups": 1,
"tsImportSorter.configuration.groupRules": ["^@angular/", "^[@]", "^(?!src|[.])", "^[^.]", "^[.]/", "^[..]/"],
"tsImportSorter.configuration.wrappingStyle": {
"maxBindingNamesPerLine": 0,
"maxDefaultAndBindingNamesPerLine": 0,
"maxExportNamesPerLine": 0,
"maxNamesPerWrappedLine": 1,
"ignoreComments": false
}
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
}
]
}
# Changelog of json2html-lib
## V0.2.0 (2022-05-30)
- Add option `wrapAttrNumber`
- Add options `prettier` on `attrPosition`
## V0.1.0 (2022-02-10)
- With Ivy partial compilation mode
- With Ivy partial compilation mode
## V0.0.6 (2020-10-21)
- Add option `optionalEndTagsFix`
- Add options `inline` and `autoclose` on json node
- fix minor bugs
- Add option `optionalEndTagsFix`
- Add options `inline` and `autoclose` on json node
- fix minor bugs
## V0.0.5 (2020-10-18)
- fix numeric options
- add demo
- fix numeric options
- add demo
## V0.0.4 (2020-10-15)
- add `xml` type of render
- code comments
- fix minor bugs
- add `xml` type of render
- code comments
- fix minor bugs
## V0.0.3 (2020-10-14)
- change to accept lists of elements or not
- change to accept lists of elements or not
## V0.0.2 (2020-10-14)
- Fix attributs render
- Fix attributs render
## V0.0.1 (2020-10-14)
- initial release
- initial release
......@@ -10,12 +10,14 @@ Generation of an HTML plain text from a Json structure with several setting opti
npm i json2html-lib --save
```
- 0.0.6 : for View Engine
- 0.1.0+ : for Ivy
- 0.0.6 : for View Engine
- 0.1.0+ : for Ivy
## Requirements
Only for demo:
- Angular 13.2.0 and more
- Angular 13.2.0 and more
## Demo
......@@ -23,23 +25,28 @@ Only for demo:
## Usage
### Examples
### Examples
```typescript
import { Json2html } from 'json2html-lib';
console.log(new Json2html({
tag: 'div',
attrs: { id: 'test1', class: 'testclasse' },
body: [
'test',
console.log(
new Json2html(
{
tag: 'div',
attrs: { id: 'test2', class: 'foobar' },
body: 'test'
}
]
}, { formatting: 'multiline' }).toString());
tag: 'div',
attrs: { id: 'test1', class: 'testclasse' },
body: [
'test',
{
tag: 'div',
attrs: { id: 'test2', class: 'foobar' },
body: 'test',
},
],
},
{ formatting: 'multiline' },
).toString(),
);
/*
<div id="test1"
class="testclasse">
......
......@@ -2,30 +2,30 @@
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../../coverage'),
reports: ['html', 'lcovonly'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../../coverage'),
reports: ['html', 'lcovonly'],
fixWebpackSourcePaths: true,
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
});
};
......@@ -4,4 +4,4 @@
"lib": {
"entryFile": "src/public_api.ts"
}
}
\ No newline at end of file
}
export interface Json2htmlAttr {
[key: string]: string | number | null;
}
......@@ -40,7 +39,9 @@ export interface Json2htmlOptions {
* * `alignTag`: alignment with the tag
* * `alignFirstAttr`: alignment with the first attribute
*/
attrPosition?: 'inline' | 'space' | 'alignTag' | 'alignFirstAttr';
attrPosition?: 'inline' | 'space' | 'alignTag' | 'alignFirstAttr' | 'prettier';
/** attr number wen 0 == 'inline' */
wrapAttrNumber?: number;
/** Format of the targeted structure */
type?: 'html' | 'xml';
/** in XML mode, auto generated tag if the only text alongside other tags */
......@@ -56,7 +57,6 @@ export interface Json2htmlOptions {
}
export class Json2html {
readonly options: Json2htmlOptions = {
spaceType: 'space',
spaceLength: 4,
......@@ -83,7 +83,7 @@ export class Json2html {
'param',
'source',
'track',
'wbr'
'wbr',
],
removeOptionalEndTags: false,
optionalEndTags: [
......@@ -103,18 +103,15 @@ export class Json2html {
'thead',
'tbody',
'tfoot',
'tr'
]
'tr',
],
};
/**
* @param json one ou list of node data
* @param option formating options
*/
constructor(
public json: Json2htmlRef | Json2htmlRef[],
option: Json2htmlOptions = {}
) {
constructor(public json: Json2htmlRef | Json2htmlRef[], option: Json2htmlOptions = {}) {
Object.assign(this.options, option);
}
......@@ -152,7 +149,7 @@ export class Json2html {
if (
!this.options.removeOptionalEndTags ||
this._modeXML() ||
this.options.removeOptionalEndTags && !this.options.optionalEndTags.includes(json.tag.toLowerCase())
(this.options.removeOptionalEndTags && !this.options.optionalEndTags.includes(json.tag.toLowerCase()))
) {
string += `</${json.tag}>`;
}
......@@ -170,33 +167,50 @@ export class Json2html {
let string = '';
const attrs = json.attrs;
if (attrs && Object.keys(attrs).length) {
const length = Object.values(json.attrs).filter(i => i !== undefined).length;
const typeAlign =
(this.options.wrapAttrNumber ?? 1) < length && !inline ? this.options.attrPosition : 'inline';
for (const id in attrs) {
if (attrs[id] !== undefined) {
let attr = '';
switch (!inline ? this.options.attrPosition : 'inline') {
switch (typeAlign) {
case 'inline':
attr += ' ';
break;
case 'space':
attr += string && this.options.indent && this._hasMultiline()
? `\n${this._getSpacing(lvl + 1)}`
: ' ';
attr +=
string && this.options.indent && this._hasMultiline()
? `\n${this._getSpacing(lvl + 1)}`
: ' ';
break;
case 'alignTag':
attr += string && this.options.indent && this._hasMultiline()
? `\n${this._getSpacing(lvl, 1)}`
: ' ';
attr +=
string && this.options.indent && this._hasMultiline()
? `\n${this._getSpacing(lvl, 1)}`
: ' ';
break;
case 'alignFirstAttr':
attr += string && this.options.indent && this._hasMultiline()
? `\n${this._getSpacing(lvl, json.tag.length + 2)}`
: ' ';
attr +=
string && this.options.indent && this._hasMultiline()
? `\n${this._getSpacing(lvl, json.tag.length + 2)}`
: ' ';
break;
case 'prettier':
attr +=
this.options.indent && this._hasMultiline() ? `\n${this._getSpacing(lvl + 1)}` : ' ';
break;
}
attr += `${id}${attrs[id] !== null || attrs[id] ? `="${attrs[id]}"` : ''}`;
string += attr;
}
}
switch (typeAlign) {
case 'prettier':
string += this.options.indent && this._hasMultiline() ? `\n${this._getSpacing(lvl)}` : ' ';
break;
}
}
return string;
}
......@@ -232,7 +246,7 @@ export class Json2html {
lvl: number,
element: Json2htmlRef | string,
onlyOne: boolean,
inline: boolean = false
inline: boolean = false,
): string {
let string = '';
if (this._hasMultiline() && !inline) {
......@@ -243,13 +257,11 @@ export class Json2html {
if (!onlyOne && this._modeXML() && typeof element === 'string') {
element = {
tag: this.options.xmlDefaultTag,
body: element
body: element,
};
}
string += typeof element === 'string'
? element
: this._generate(lvl + 1, element, inline);
string += typeof element === 'string' ? element : this._generate(lvl + 1, element, inline);
return string;
}
......@@ -275,9 +287,9 @@ export class Json2html {
*/
private _getSpacing(lvl: number, addition: number = 0): string {
return this.options.indent
? (this.options.spaceType === 'space' ? ' ' : '\t')
.repeat((lvl + +this.options.spaceBase) * +this.options.spaceLength) + ' '.repeat(addition)
? (this.options.spaceType === 'space' ? ' ' : '\t').repeat(
(lvl + +this.options.spaceBase) * +this.options.spaceLength,
) + ' '.repeat(addition)
: '';
}
}
......@@ -3,21 +3,20 @@
import 'core-js/es7/reflect';
import 'zone.js';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false }
}
);
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false },
});
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
......
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule { }
export class AppRoutingModule {}
<h1>json2html-lib</h1>
<div>
<button type="button"
(click)="updateExample(0)">Example 1</button>
<button type="button"
(click)="updateExample(1)">Example 2</button>
<button type="button" (click)="updateExample(0)">Example 1</button>
<button type="button" (click)="updateExample(1)">Example 2</button>
</div>
<main>
<fieldset class="json">
<legend>json</legend>
<textarea (change)="format($event.target.value)">{{data | json}}</textarea>
<textarea (change)="format($event.target.value)">{{ data | json }}</textarea>
</fieldset>
<fieldset class="options">
......@@ -18,93 +16,109 @@
<div>
<label>
<span>formatting</span>
<select [value]="formatting"
(change)="formatting = $event.target.value; generated()">
<option value="multiline">multiline (defaut): structure sur plusieur lignes avec indentation
possible</option>
<select [value]="formatting" (change)="formatting = $event.target.value; generated()">
<option value="multiline">
multiline (defaut): structure sur plusieur lignes avec indentation possible
</option>
<option value="inline">inline: all on one line without space</option>
</select>
</label>
<label *ngIf="formatting === 'multiline'">
<span>indent</span>
<input type="checkbox"
[checked]="indent"
(change)="indent = $event.target.checked; generated()">
<input type="checkbox" [checked]="indent" (change)="indent = $event.target.checked; generated()" />
</label>
<label *ngIf="indent && formatting === 'multiline'">
<span>spaceType</span>
<select [value]="spaceType"
(change)="spaceType = $event.target.value; generated()">
<select [value]="spaceType" (change)="spaceType = $event.target.value; generated()">
<option value="space">space (defaut)</option>
<option value="tab">tab</option>
</select>
</label>
<label *ngIf="indent && formatting === 'multiline'">
<span>spaceLength</span>
<input [value]="spaceLength"
type="number"
min="0"
(change)="spaceLength = $event.target.value; generated()">
<input
[value]="spaceLength"
type="number"
min="0"
(change)="spaceLength = $event.target.value; generated()"
/>
</label>
<label *ngIf="indent && formatting === 'multiline'">
<span>spaceBase</span>
<input [value]="spaceBase"
type="number"
min="0"
(change)="spaceBase = $event.target.value; generated()">
<input
[value]="spaceBase"
type="number"
min="0"
(change)="spaceBase = $event.target.value; generated()"
/>
</label>
<label *ngIf="indent && formatting === 'multiline'">
<span>attrPosition</span>
<select [value]="attrPosition"
(change)="attrPosition = $event.target.value; generated()">
<select [value]="attrPosition" (change)="attrPosition = $event.target.value; generated()">
<option value="inline">inline: no alignment</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>
<option value="prettier">prettier: like Prettier formatter</option>
</select>
</label>
<label>
<span>wrapAttrNumber</span>
<input
[value]="wrapAttrNumber"
type="number"
min="0"
(change)="wrapAttrNumber = $event.target.value; generated()"
/>
</label>
<label>
<span>type</span>
<select [value]="type"
(change)="type = $event.target.value; generated()">
<select [value]="type" (change)="type = $event.target.value; generated()">
<option value="html">html (default)</option>
<option value="xml">xml</option>
</select>
</label>
<label>
<span>xmlDefaultTag</span>
<input type="text"
[value]="xmlDefaultTag"
(change)="xmlDefaultTag = $event.target.value; generated()">
<input
type="text"
[value]="xmlDefaultTag"
(change)="xmlDefaultTag = $event.target.value; generated()"
/>
</label>
<label>
<span>noContentTags</span>
<input type="text"
[value]="noContentTags"
(change)="noContentTags = $event.target.value; generated()">
<input