<commit_before>/** @jsx jsx */
import { jsx } from '@emotion/core';
import { useMemo } from 'react';
import * as image from './image';
import * as caption from './caption';
import insertImages from 'slate-drop-or-paste-images';
import imageExtensions from 'image-extensions';
import { findNode } from 'slate-react';
import { Block } from 'slate';

export let type = 'image-container';

let getFiles = () =>
  new Promise(resolve => {
    let input = document.createElement('input');
    input.type = 'file';
    input.onchange = () => {
      let files = input.files;
      Promise.all(
        [...files].map(file => {
          return new Promise(innerResolve => {
            const reader = new FileReader();
            reader.onload = e => {
              innerResolve(e.target.result);
            };
            reader.readAsDataURL(file);
          });
        })
      ).then(resolve);
    };
    input.click();
  });

export function Sidebar({ editor }) {
  return (
    <button
      type="button"
      onClick={() => {
        getFiles().then(srcs => {
          srcs.forEach(src => {
            editor.insertBlock({
              type,
              nodes: [
                Block.create({
                  type: image.type,
                  data: {
                    src,
                  },
                }),
              ],
            });
          });
        });
      }}
    >
      Insert Image
    </button>
  );
}

function getImageStyle(alignment) {
  if (alignment === 'left') {
    return {
      float: 'left',
      marginRight: '10px',
      width: '50%',
    };
  } else if (alignment === 'right') {
    return {
      float: 'right',
      marginLeft: '10px',
      width: '50%',
    };
  } else {
    return {
      display: 'block',
      margin: '0px auto',
      width: '100%',
    };
  }
}
export function Node(props) {
  let alignment = props.node.data.get('alignment');
  return (
    <figure
      css={{ display: 'flex', flexDirection: 'column', ...getImageStyle(alignment) }}
      {...props.attributes}
    >
      <image.ImageAlignmentContext.Provider
        value={useMemo(
          () => {
            return {
              alignment,
              onAlignmentChange(newAlignment) {
                props.editor.setNodeByKey(props.node.key, {
                  data: props.node.data.set('alignment', newAlignment),
                });
              },
            };
          },
          [props.node.key, alignment, props.editor, props.node.data]
        )}
      >
        {props.children}
      </image.ImageAlignmentContext.Provider>
    </figure>
  );
}

export let schema = {
  nodes: [
    {
      match: [{ type: image.type }],
      min: 1,
      max: 1,
    },
    {
      match: [{ type: caption.type }],
      min: 1,
      max: 1,
    },
  ],
  normalize(editor, error) {
    switch (error.code) {
      case 'child_min_invalid': {
        if (error.index === 0) {
          // the image has been deleted so we also want to delete the image-container
          editor.removeNodeByKey(error.node.key);
        }
        if (error.index === 1) {
          // the caption has been deleted
          // the user probably doesn't want to delete the image
          // they probably just wanted to remove everything in the caption
          // so the caption gets removed,  we insert another caption
          editor.insertNodeByKey(error.node.key, 1, Block.create('caption'));
        }
        return;
      }
      case 'node_data_invalid': {
        if (error.key === 'alignment') {
          editor.setNodeByKey(error.node.key, {
            data: error.node.data.set('alignment', 'center'),
          });
        }
        return;
      }
    }
    console.log(error);
  },
  data: {
    alignment(value) {
      switch (value) {
        case 'center':
        case 'left':
        case 'right': {
          return true;
        }
      }
      return false;
    },
  },
};

export let plugins = [
  insertImages({
    extensions: imageExtensions,
    insertImage: (editor, file) => {
      const reader = new FileReader();
      reader.onload = () => {
        editor.insertBlock({
          type,
          nodes: [
            Block.create({
              type: image.type,
              data: {
                src: reader.result,
              },
            }),
          ],
        });
      };
      reader.readAsDataURL(file);
    },
  }),
  {
    onDragStart(event, editor, next) {
      const { value } = editor;
      const { document } = value;
      const node = findNode(event.target, editor);
      if (node.type === image.type) {
        const ancestors = document.getAncestors(node.key);
        let imgContainer = ancestors.get(ancestors.size - 1);
        if (imgContainer.type === type) {
          editor.moveToRangeOfNode(imgContainer);
        }
      }

      next();
    },
  },
];

export let dependencies = [image, caption];<commit_msg>Simplify image loading content block<commit_after>/** @jsx jsx */
import { jsx } from '@emotion/core';
import { useMemo } from 'react';
import * as image from './image';
import * as caption from './caption';
import insertImages from 'slate-drop-or-paste-images';
import imageExtensions from 'image-extensions';
import { findNode } from 'slate-react';
import { Block } from 'slate';

export let type = 'image-container';

let getFiles = () =>
  new Promise(resolve => {
    let input = document.createElement('input');
    input.type = 'file';
    input.onchange = () => resolve([...input.files]);
    input.click();
  });

const insertImageBlockFromFile = (editor, file) => {
  const reader = new FileReader();
  reader.onload = event => insertImageBlock(editor, event.target.result);
  reader.readAsDataURL(file);
};

const insertImageBlock = (editor, src) => {
  editor.insertBlock({
    type,
    nodes: [
      Block.create({
        type: image.type,
        data: { src },
      }),
    ],
  });
};

export function Sidebar({ editor }) {
  return (
    <button
      type="button"
      onClick={() => {
        getFiles().then(files => {
          files.forEach(file => insertImageBlockFromFile(editor, file));
        });
      }}
    >
      Insert Image
    </button>
  );
}

function getImageStyle(alignment) {
  if (alignment === 'left') {
    return {
      float: 'left',
      marginRight: '10px',
      width: '50%',
    };
  } else if (alignment === 'right') {
    return {
      float: 'right',
      marginLeft: '10px',
      width: '50%',
    };
  } else {
    return {
      display: 'block',
      margin: '0px auto',
      width: '100%',
    };
  }
}
export function Node(props) {
  let alignment = props.node.data.get('alignment');
  return (
    <figure
      css={{ display: 'flex', flexDirection: 'column', ...getImageStyle(alignment) }}
      {...props.attributes}
    >
      <image.ImageAlignmentContext.Provider
        value={useMemo(
          () => {
            return {
              alignment,
              onAlignmentChange(newAlignment) {
                props.editor.setNodeByKey(props.node.key, {
                  data: props.node.data.set('alignment', newAlignment),
                });
              },
            };
          },
          [props.node.key, alignment, props.editor, props.node.data]
        )}
      >
        {props.children}
      </image.ImageAlignmentContext.Provider>
    </figure>
  );
}

export let schema = {
  nodes: [
    {
      match: [{ type: image.type }],
      min: 1,
      max: 1,
    },
    {
      match: [{ type: caption.type }],
      min: 1,
      max: 1,
    },
  ],
  normalize(editor, error) {
    switch (error.code) {
      case 'child_min_invalid': {
        if (error.index === 0) {
          // the image has been deleted so we also want to delete the image-container
          editor.removeNodeByKey(error.node.key);
        }
        if (error.index === 1) {
          // the caption has been deleted
          // the user probably doesn't want to delete the image
          // they probably just wanted to remove everything in the caption
          // so the caption gets removed,  we insert another caption
          editor.insertNodeByKey(error.node.key, 1, Block.create('caption'));
        }
        return;
      }
      case 'node_data_invalid': {
        if (error.key === 'alignment') {
          editor.setNodeByKey(error.node.key, {
            data: error.node.data.set('alignment', 'center'),
          });
        }
        return;
      }
    }
    console.log(error);
  },
  data: {
    alignment(value) {
      switch (value) {
        case 'center':
        case 'left':
        case 'right': {
          return true;
        }
      }
      return false;
    },
  },
};

export let plugins = [
  insertImages({
    extensions: imageExtensions,
    insertImage: insertImageBlockFromFile,
  }),
  {
    onDragStart(event, editor, next) {
      const { value } = editor;
      const { document } = value;
      const node = findNode(event.target, editor);
      if (node.type === image.type) {
        const ancestors = document.getAncestors(node.key);
        let imgContainer = ancestors.get(ancestors.size - 1);
        if (imgContainer.type === type) {
          editor.moveToRangeOfNode(imgContainer);
        }
      }

      next();
    },
  },
];

export let dependencies = [image, caption];
{'fraction_non_alphanumeric': 0.1425208645409801, 'fraction_numerical': 0.004279905842071475, 'mean_word_length': 1.7893166219039094, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 37, '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': '4627792', 'n_tokens_mistral': 2785, 'n_tokens_neox': 2712, 'n_words': 622}