<commit_before>import { cloneDeep } from 'lodash-es';
import { usePageComponentStore } from '../../../Components/PageComponents/tools/componentFactory';
import {
  actionsChoices,
  decorationsChoices,
  layoutCommonChoices,
  layoutConditionnalChoices,
} from '../../../Components/PageComponents/tools/options';
import { AvailableSchemas } from '../FormView';
import { hashListChoicesToSchema } from '../FormView/HashList';
import { wegasComponentCommonSchema } from '../Page/ComponentProperties';

/**
 * useJSONSchema - Creates the schema for the JSON of a page
 */
export function useJSONSchema() {
  const components = usePageComponentStore(s => s);
  const childrenLayoutOptionSchema = Object.values(components)
    .filter(component => component.container?.childrenLayoutOptionSchema)
    .reduce((o, c) => [...o, ...c.container!.childrenLayoutOptionSchema!], []);

  const componentSchemas = Object.values(components).map(component => {
    const componentSchemaProperties = cloneDeep(
      component.schema.properties || {},
    );
    if ('children' in componentSchemaProperties) {
      componentSchemaProperties['children'] = {
        type: 'array',
        required: true,
        items: {
          $ref: '#/definitions/___self',
        },
      } as AvailableSchemas;
    }

    const properties = {
      ...wegasComponentCommonSchema,
      ...componentSchemaProperties,
      ...component.container?.childrenAdditionalShema,
      ...hashListChoicesToSchema([
        // ...Object.values(layoutChoices).reduce((o, c) => [...o, ...c], []),
        ...childrenLayoutOptionSchema,
        ...layoutCommonChoices,
      ]),
      ...hashListChoicesToSchema(layoutConditionnalChoices),
      ...hashListChoicesToSchema(actionsChoices),
      ...hashListChoicesToSchema(decorationsChoices),
    };

    const requiredProperties = Object.entries(properties).reduce(
      (o, [type, component]) => (component.required ? [...o, type] : o),
      [],
    );

    return {
      type: 'object',
      required: ['type', 'props'],
      isContainer: component.container != null,
      properties: {
        type: {
          type: 'string',
          enum: [component.componentId],
        },
        props: {
          type: 'object',
          required: requiredProperties,
          properties: {
            ...wegasComponentCommonSchema,
            ...componentSchemaProperties,
            ...hashListChoicesToSchema([
              ...childrenLayoutOptionSchema,
              ...layoutCommonChoices,
            ]),
            ...hashListChoicesToSchema(layoutConditionnalChoices),
            ...hashListChoicesToSchema(actionsChoices),
            ...hashListChoicesToSchema(decorationsChoices),
          },
        },
      },
    };
  });

  return {
    oneOf: componentSchemas.filter(component => component.isContainer),
    definitions: {
      ___self: {
        allOf: [
          {
            $ref: '#/definitions/components',
          },
          {
            type: 'object',
            properties: {
              type: {},
              props: {},
            },
            additionalProperties: false,
          },
        ],
      },
      components: {
        defaultSnippets: [
          {
            label: 'New Component',
            body: {
              type: '$1',
            },
          },
        ],
        oneOf: componentSchemas,
      },
    },
  };
}<commit_msg>[editor] improve monaco smoothness<commit_after>import { cloneDeep } from 'lodash-es';
import * as React from 'react';
import { usePageComponentStore } from '../../../Components/PageComponents/tools/componentFactory';
import {
  actionsChoices,
  decorationsChoices,
  layoutCommonChoices,
  layoutConditionnalChoices,
} from '../../../Components/PageComponents/tools/options';
import { AvailableSchemas } from '../FormView';
import { hashListChoicesToSchema } from '../FormView/HashList';
import { wegasComponentCommonSchema } from '../Page/ComponentProperties';

/**
 * useJSONSchema - Creates the schema for the JSON of a page
 */
export function useJSONSchema() {
  const components = usePageComponentStore(s => s);

  const pageStoreRef = React.useRef(components);

  const resultRef = React.useRef<unknown>(undefined);

  if (components === pageStoreRef.current && resultRef.current != null) {
    // As this funciton is quite slow (deepClone of big objects), mitigates recomputation
    //
    // page store did not change && and result has already been computed
    // return saved value
    return resultRef.current;
  }

  pageStoreRef.current = components;

  const childrenLayoutOptionSchema = Object.values(components)
    .filter(component => component.container?.childrenLayoutOptionSchema)
    .reduce((o, c) => [...o, ...c.container!.childrenLayoutOptionSchema!], []);

  const componentSchemas = Object.values(components).map(component => {
    const componentSchemaProperties = cloneDeep(
      component.schema.properties || {},
    );
    if ('children' in componentSchemaProperties) {
      componentSchemaProperties['children'] = {
        type: 'array',
        required: true,
        items: {
          $ref: '#/definitions/___self',
        },
      } as AvailableSchemas;
    }

    const properties = {
      ...wegasComponentCommonSchema,
      ...componentSchemaProperties,
      ...component.container?.childrenAdditionalShema,
      ...hashListChoicesToSchema([
        // ...Object.values(layoutChoices).reduce((o, c) => [...o, ...c], []),
        ...childrenLayoutOptionSchema,
        ...layoutCommonChoices,
      ]),
      ...hashListChoicesToSchema(layoutConditionnalChoices),
      ...hashListChoicesToSchema(actionsChoices),
      ...hashListChoicesToSchema(decorationsChoices),
    };

    //  extract name of required properties
    const requiredProperties = Object.entries(properties)
      .filter(([, comp]) => comp.required)
      .map(([type]) => type);

    return {
      type: 'object',
      required: ['type', 'props'],
      isContainer: component.container != null,
      properties: {
        type: {
          type: 'string',
          enum: [component.componentId],
        },
        props: {
          type: 'object',
          required: requiredProperties,
          properties: {
            ...wegasComponentCommonSchema,
            ...componentSchemaProperties,
            ...hashListChoicesToSchema([
              ...childrenLayoutOptionSchema,
              ...layoutCommonChoices,
            ]),
            ...hashListChoicesToSchema(layoutConditionnalChoices),
            ...hashListChoicesToSchema(actionsChoices),
            ...hashListChoicesToSchema(decorationsChoices),
          },
        },
      },
    };
  });

  const result = {
    oneOf: componentSchemas.filter(component => component.isContainer),
    definitions: {
      ___self: {
        allOf: [
          {
            $ref: '#/definitions/components',
          },
          {
            type: 'object',
            properties: {
              type: {},
              props: {},
            },
            additionalProperties: false,
          },
        ],
      },
      components: {
        defaultSnippets: [
          {
            label: 'New Component',
            body: {
              type: '$1',
            },
          },
        ],
        oneOf: componentSchemas,
      },
    },
  };

  resultRef.current = result;
  return result;
}
{'fraction_non_alphanumeric': 0.13336925771251515, 'fraction_numerical': 0.000269432843863667, 'mean_word_length': 2.1726495726495725, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6991899', 'n_tokens_mistral': 1975, 'n_tokens_neox': 1911, 'n_words': 365}