/* * Copyright 2021 Juan Cruz Viotti * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import CodeMirror from 'codemirror' import { JSONStats, JSONStatsSummary, summarize, analyze, qualify } from '../contrib/jsonstats' import { JSONValue, JSONObject } from '../lib/json' const EXAMPLE_JSON: JSONObject = { tags: [], tz: -25200, days: [ 1, 1, 2, 1 ], coord: [ -90.0715, 29.9510 ], data: [ { name: 'ox03', staff: true }, { name: null, staff: false, extra: { info: '' } }, { name: 'ox03', staff: true }, {} ] } const editorElement: HTMLElement | null = document.getElementById('editor') if (editorElement === null) { throw new Error('Editor element does not exist') } const code: CodeMirror.Editor = CodeMirror(editorElement, { lineNumbers: true, value: JSON.stringify(EXAMPLE_JSON, null, 2), theme: 'idea', mode: 'json' }) const buttonElement: HTMLElement | null = document.getElementById('analyze') if (buttonElement === null) { throw new Error('Button element does not exist') } const parseJSON = (value: string): JSONValue => { try { const result: JSONValue = JSON.parse(value) return result } catch (error) { if (error instanceof SyntaxError) { document.querySelectorAll('.error-modal').forEach((element: Element) => { element.classList.remove('hidden') }) } throw error } } const ANALYZE_VALUES_STRUCTURAL_COUNT: HTMLElement | null = document.getElementById('analyze-values-structural-count') const ANALYZE_VALUES_STRUCTURAL_BYTESIZE: HTMLElement | null = document.getElementById('analyze-values-structural-bytesize') const ANALYZE_VALUES_NUMERIC_COUNT: HTMLElement | null = document.getElementById('analyze-values-numeric-count') const ANALYZE_VALUES_NUMERIC_BYTESIZE: HTMLElement | null = document.getElementById('analyze-values-numeric-bytesize') const ANALYZE_VALUES_BOOLEAN_COUNT: HTMLElement | null = document.getElementById('analyze-values-boolean-count') const ANALYZE_VALUES_BOOLEAN_BYTESIZE: HTMLElement | null = document.getElementById('analyze-values-boolean-bytesize') const ANALYZE_VALUES_TEXTUAL_COUNT: HTMLElement | null = document.getElementById('analyze-values-textual-count') const ANALYZE_VALUES_TEXTUAL_BYTESIZE: HTMLElement | null = document.getElementById('analyze-values-textual-bytesize') const ANALYZE_KEYS_COUNT: HTMLElement | null = document.getElementById('analyze-keys-count') const ANALYZE_KEYS_BYTESIZE: HTMLElement | null = document.getElementById('analyze-keys-bytesize') const ANALYZE_LARGEST_LEVEL: HTMLElement | null = document.getElementById('analyze-largest-level') const ANALYZE_HEIGHT: HTMLElement | null = document.getElementById('analyze-height') const ANALYZE_DUPLICATED_KEYS: HTMLElement | null = document.getElementById('analyze-duplicated-keys') const ANALYZE_DUPLICATED_VALUES: HTMLElement | null = document.getElementById('analyze-duplicated-values') const ANALYZE_BYTESIZE: HTMLElement | null = document.getElementById('analyze-bytesize') if (ANALYZE_VALUES_STRUCTURAL_COUNT === null || ANALYZE_VALUES_STRUCTURAL_BYTESIZE === null || ANALYZE_VALUES_NUMERIC_COUNT === null || ANALYZE_VALUES_NUMERIC_BYTESIZE === null || ANALYZE_VALUES_BOOLEAN_COUNT === null || ANALYZE_VALUES_BOOLEAN_BYTESIZE === null || ANALYZE_VALUES_TEXTUAL_COUNT === null || ANALYZE_VALUES_TEXTUAL_BYTESIZE === null || ANALYZE_KEYS_COUNT === null || ANALYZE_KEYS_BYTESIZE === null || ANALYZE_LARGEST_LEVEL === null || ANALYZE_HEIGHT === null || ANALYZE_DUPLICATED_KEYS === null || ANALYZE_DUPLICATED_VALUES === null || ANALYZE_BYTESIZE === null) { throw new Error('Not all analyze elements exist') } const SUMMARY_SIZE: HTMLElement | null = document.getElementById('summary-size') const SUMMARY_KEYS_REDUNDANCY: HTMLElement | null = document.getElementById('summary-keys-redundancy') const SUMMARY_VALUES_REDUNDANCY: HTMLElement | null = document.getElementById('summary-values-redundancy') const SUMMARY_NESTING_WEIGHT: HTMLElement | null = document.getElementById('summary-nesting-weight') const SUMMARY_NUMERIC_WEIGHT: HTMLElement | null = document.getElementById('summary-numeric-weight') const SUMMARY_TEXTUAL_WEIGHT: HTMLElement | null = document.getElementById('summary-textual-weight') const SUMMARY_BOOLEAN_WEIGHT: HTMLElement | null = document.getElementById('summary-boolean-weight') const SUMMARY_STRUCTURAL_WEIGHT: HTMLElement | null = document.getElementById('summary-structural-weight') if (SUMMARY_SIZE === null || SUMMARY_KEYS_REDUNDANCY === null || SUMMARY_VALUES_REDUNDANCY === null || SUMMARY_NESTING_WEIGHT === null || SUMMARY_NUMERIC_WEIGHT === null || SUMMARY_TEXTUAL_WEIGHT === null || SUMMARY_BOOLEAN_WEIGHT === null || SUMMARY_STRUCTURAL_WEIGHT === null) { throw new Error('Not all summary elements exist') } const QUALIFIERS_CONTAINER: HTMLElement | null = document.getElementById('qualifiers') if (QUALIFIERS_CONTAINER === null) { throw new Error('The qualifiers container does not exist') } const capitalize = (text: string): string => { return text[0].toUpperCase() + text.slice(1) } const populate = (contents: string): void => { const json: JSONValue = parseJSON(contents) const stats: JSONStats = analyze(json) ANALYZE_BYTESIZE.innerHTML = String(stats.byteSize) ANALYZE_DUPLICATED_KEYS.innerHTML = String(stats.duplicatedKeys) ANALYZE_DUPLICATED_VALUES.innerHTML = String(stats.duplicatedValues) ANALYZE_HEIGHT.innerHTML = String(stats.height) ANALYZE_LARGEST_LEVEL.innerHTML = String(stats.largestLevel) ANALYZE_KEYS_COUNT.innerHTML = String(stats.keys.count) ANALYZE_KEYS_BYTESIZE.innerHTML = String(stats.keys.byteSize) ANALYZE_VALUES_NUMERIC_COUNT.innerHTML = String(stats.values.numeric.count) ANALYZE_VALUES_NUMERIC_BYTESIZE.innerHTML = String(stats.values.numeric.byteSize) ANALYZE_VALUES_BOOLEAN_COUNT.innerHTML = String(stats.values.boolean.count) ANALYZE_VALUES_BOOLEAN_BYTESIZE.innerHTML = String(stats.values.boolean.byteSize) ANALYZE_VALUES_TEXTUAL_COUNT.innerHTML = String(stats.values.textual.count) ANALYZE_VALUES_TEXTUAL_BYTESIZE.innerHTML = String(stats.values.textual.byteSize) ANALYZE_VALUES_STRUCTURAL_COUNT.innerHTML = String(stats.values.structural.count) ANALYZE_VALUES_STRUCTURAL_BYTESIZE.innerHTML = String(stats.values.structural.byteSize) const summary: JSONStatsSummary = summarize(stats) SUMMARY_SIZE.innerHTML = summary.size SUMMARY_NESTING_WEIGHT.innerHTML = String(summary.nestingWeight) const precision: number = 4 SUMMARY_KEYS_REDUNDANCY.innerHTML = summary.keysRedundancy.toFixed(precision) SUMMARY_VALUES_REDUNDANCY.innerHTML = summary.valuesRedundancy.toFixed(precision) SUMMARY_NUMERIC_WEIGHT.innerHTML = summary.numericWeight.toFixed(precision) SUMMARY_TEXTUAL_WEIGHT.innerHTML = summary.textualWeight.toFixed(precision) SUMMARY_BOOLEAN_WEIGHT.innerHTML = summary.booleanWeight.toFixed(precision) SUMMARY_STRUCTURAL_WEIGHT.innerHTML = summary.structuralWeight.toFixed(precision) QUALIFIERS_CONTAINER.innerHTML = qualify(summary).map(capitalize).join(', ') } buttonElement.addEventListener('click', () => { const contents: string = code.getValue() populate(contents) }) const modalButtonElement: HTMLElement | null = document.getElementById('close-modal') if (modalButtonElement === null) { throw new Error('Modal button element does not exist') } modalButtonElement.addEventListener('click', () => { document.querySelectorAll('.error-modal').forEach((element: Element) => { element.classList.add('hidden') }) }) // Analyze example populate(code.getValue())