UNPKG

ketcher-react

Version:
1,113 lines (1,093 loc) 2.12 MB
/**************************************************************************** * Copyright 2021 EPAM Systems * * 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. ***************************************************************************/ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _defineProperty$1 = require('@babel/runtime/helpers/defineProperty'); var _slicedToArray$1 = require('@babel/runtime/helpers/slicedToArray'); var jsxRuntime = require('react/jsx-runtime'); var React = require('react'); require('intersection-observer'); require('element-closest-polyfill'); require('regenerator-runtime/runtime'); require('url-search-params-polyfill'); require('whatwg-fetch'); var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator'); var _regeneratorRuntime = require('@babel/runtime/regenerator'); var _classCallCheck$2 = require('@babel/runtime/helpers/classCallCheck'); var _createClass$2 = require('@babel/runtime/helpers/createClass'); var ketcherCore = require('ketcher-core'); var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties'); var _possibleConstructorReturn$2 = require('@babel/runtime/helpers/possibleConstructorReturn'); var _getPrototypeOf$2 = require('@babel/runtime/helpers/getPrototypeOf'); var _inherits$2 = require('@babel/runtime/helpers/inherits'); var clsx = require('clsx'); var _typeof$3 = require('@babel/runtime/helpers/typeof'); var Ajv = require('ajv'); var fp = require('lodash/fp'); var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray'); var _ = require('lodash'); var _taggedTemplateLiteral = require('@babel/runtime/helpers/taggedTemplateLiteral'); var styled = require('@emotion/styled'); var react = require('@emotion/react'); var KN = require('w3c-keyname'); var require$$0$2 = require('util'); var ReactDOM = require('react-dom'); var reactRedux = require('react-redux'); var redux = require('redux'); var CFB = require('cfb'); require('redux-logger'); var thunkMiddleware = require('redux-thunk'); var useResizeObserver = require('use-resize-observer/polyfilled'); var reactIntersectionObserver = require('react-intersection-observer'); var material = require('@mui/material'); var reselect = require('reselect'); var reactDeviceDetect = require('react-device-detect'); var _classPrivateFieldGet = require('@babel/runtime/helpers/classPrivateFieldGet'); var _classPrivateFieldSet = require('@babel/runtime/helpers/classPrivateFieldSet'); var _assertThisInitialized$2 = require('@babel/runtime/helpers/assertThisInitialized'); var subscription = require('subscription'); var reactContexify = require('react-contexify'); require('react-contexify/ReactContexify.css'); var MuiSelect = require('@mui/material/Select'); var Divider$2 = require('@mui/material/Divider'); var MenuItem = require('@mui/material/MenuItem'); var reactColorful = require('react-colorful'); var fileSaver$1 = require('file-saver'); var FontFaceObserver = require('font-face-observer'); var reactDropzone = require('react-dropzone'); var Accordion$2 = require('@mui/material/Accordion'); var AccordionSummary = require('@mui/material/AccordionSummary'); var AccordionDetails = require('@mui/material/AccordionDetails'); var Tabs$1 = require('@mui/material/Tabs'); var Tab = require('@mui/material/Tab'); require('draft-js/dist/Draft.css'); var draftJs = require('draft-js'); var createStyles = require('draft-js-custom-styles'); var _objectDestructuringEmpty = require('@babel/runtime/helpers/objectDestructuringEmpty'); var _extends$3n = require('@babel/runtime/helpers/extends'); var MuiAutocomplete = require('@mui/material/Autocomplete'); var client = require('react-dom/client'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty$1); var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray$1); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var React__namespace = /*#__PURE__*/_interopNamespace(React); var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator); var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime); var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck$2); var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass$2); var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutProperties); var _possibleConstructorReturn__default = /*#__PURE__*/_interopDefaultLegacy(_possibleConstructorReturn$2); var _getPrototypeOf__default = /*#__PURE__*/_interopDefaultLegacy(_getPrototypeOf$2); var _inherits__default = /*#__PURE__*/_interopDefaultLegacy(_inherits$2); var clsx__default = /*#__PURE__*/_interopDefaultLegacy(clsx); var _typeof__default = /*#__PURE__*/_interopDefaultLegacy(_typeof$3); var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv); var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray); var ___default = /*#__PURE__*/_interopDefaultLegacy(_); var _taggedTemplateLiteral__default = /*#__PURE__*/_interopDefaultLegacy(_taggedTemplateLiteral); var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled); var KN__namespace = /*#__PURE__*/_interopNamespace(KN); var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0$2); var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM); var CFB__namespace = /*#__PURE__*/_interopNamespace(CFB); var thunkMiddleware__default = /*#__PURE__*/_interopDefaultLegacy(thunkMiddleware); var useResizeObserver__default = /*#__PURE__*/_interopDefaultLegacy(useResizeObserver); var _classPrivateFieldGet__default = /*#__PURE__*/_interopDefaultLegacy(_classPrivateFieldGet); var _classPrivateFieldSet__default = /*#__PURE__*/_interopDefaultLegacy(_classPrivateFieldSet); var _assertThisInitialized__default = /*#__PURE__*/_interopDefaultLegacy(_assertThisInitialized$2); var MuiSelect__default = /*#__PURE__*/_interopDefaultLegacy(MuiSelect); var Divider__default = /*#__PURE__*/_interopDefaultLegacy(Divider$2); var MenuItem__default = /*#__PURE__*/_interopDefaultLegacy(MenuItem); var FontFaceObserver__default = /*#__PURE__*/_interopDefaultLegacy(FontFaceObserver); var Accordion__default = /*#__PURE__*/_interopDefaultLegacy(Accordion$2); var AccordionSummary__default = /*#__PURE__*/_interopDefaultLegacy(AccordionSummary); var AccordionDetails__default = /*#__PURE__*/_interopDefaultLegacy(AccordionDetails); var Tabs__default = /*#__PURE__*/_interopDefaultLegacy(Tabs$1); var Tab__default = /*#__PURE__*/_interopDefaultLegacy(Tab); var createStyles__default = /*#__PURE__*/_interopDefaultLegacy(createStyles); var _objectDestructuringEmpty__default = /*#__PURE__*/_interopDefaultLegacy(_objectDestructuringEmpty); var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends$3n); var MuiAutocomplete__default = /*#__PURE__*/_interopDefaultLegacy(MuiAutocomplete); function createApi(structServiceProvider, defaultOptions) { var _structService$destro; var structService = structServiceProvider.createStructService(defaultOptions); var info = structService.info(); return Object.assign(info, { info: structService.info.bind(structService), convert: structService.convert.bind(structService), layout: structService.layout.bind(structService), clean: structService.clean.bind(structService), aromatize: structService.aromatize.bind(structService), dearomatize: structService.dearomatize.bind(structService), calculateCip: structService.calculateCip.bind(structService), automap: structService.automap.bind(structService), check: structService.check.bind(structService), calculate: structService.calculate.bind(structService), recognize: structService.recognize.bind(structService), generateImageAsBase64: structService.generateImageAsBase64.bind(structService), getInChIKey: structService.getInChIKey.bind(structService), toggleExplicitHydrogens: structService.toggleExplicitHydrogens.bind(structService), destroy: (_structService$destro = structService.destroy) === null || _structService$destro === void 0 ? void 0 : _structService$destro.bind(structService) }); } var appContext = React__default["default"].createContext({}); var errorsContext = React__default["default"].createContext({}); var settingsContext = React__default["default"].createContext({}); var formContext = React__default["default"].createContext(null); var basicAtoms = ['H', 'C', 'N', 'O', 'S', 'P', 'F', 'Cl', 'Br', 'I']; var atomCuts = { H: 'h', C: 'c', N: 'n', O: 'o', S: 's', P: 'p', F: 'f', Cl: 'l', Br: 'b', I: 'i', A: 'a', Q: 'q', R: 'r', K: 'k', M: 'm', Si: 'Shift+s', Na: 'Shift+n', X: 'x', D: 'd', B: 'Shift+b' }; var atoms = Object.keys(atomCuts).reduce(function (res, label) { res["atom-".concat(label.toLowerCase())] = { title: "Atom ".concat(label), shortcut: atomCuts[label], action: { tool: 'atom', opts: { label: label } } }; return res; }, {}); function copyAs(type) { var state = global.currentState; var editor = state.editor; var struct = editor.structSelected(); var errorHandler = editor.errorHandler; var serializer; try { switch (type) { case 'mol': { serializer = new ketcherCore.MolSerializer(); break; } case 'ket': { serializer = new ketcherCore.KetSerializer(); break; } default: { serializer = new ketcherCore.KetSerializer(); break; } } var simpleObjectOrText = Boolean(struct.simpleObjects.size || struct.texts.size); if (simpleObjectOrText && serializer instanceof ketcherCore.MolSerializer) { errorHandler('This feature is not available for Simple objects and Text objects'); return null; } var structData = serializer.serialize(struct); if (window.clipboardData) { window.clipboardData.setData('text', structData); } else { navigator.clipboard.writeText(structData); } } catch (e) { ketcherCore.KetcherLogger.error('copyAs.js::copyAs', e); errorHandler('This feature is not available in your browser'); } } function copyImageToClipboard() { return _copyImageToClipboard.apply(this, arguments); } function _copyImageToClipboard() { _copyImageToClipboard = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee() { var state, editor, server, options, struct, errorHandler, factory, service, structStr, ketcher, image, item; return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: state = global.currentState; editor = state.editor; server = state.server; options = state.options; struct = editor.structSelected(); errorHandler = editor.errorHandler; _context.prev = 6; factory = new ketcherCore.FormatterFactory(server); service = factory.create('ket', options); _context.next = 11; return service.getStructureFromStructAsync(struct); case 11: structStr = _context.sent; ketcher = new ketcherCore.Ketcher(editor, server, {}, factory); _context.next = 15; return ketcher.generateImage(structStr, { outputFormat: 'png', backgroundColor: '255, 255, 255', bondThickness: options.settings.bondThickness || ketcherCore.defaultBondThickness }); case 15: image = _context.sent; item = new ClipboardItem(_defineProperty__default["default"]({}, image.type, image)); _context.next = 19; return navigator.clipboard.write([item]); case 19: _context.next = 25; break; case 21: _context.prev = 21; _context.t0 = _context["catch"](6); ketcherCore.KetcherLogger.error('copyImageToClipboard.js::copyImageToClipboard', _context.t0); errorHandler('This feature is not available in your browser'); case 25: case "end": return _context.stop(); } }, _callee, null, [[6, 21]]); })); return _copyImageToClipboard.apply(this, arguments); } function isHidden(options, buttonName) { var _options$buttons; return Boolean((_options$buttons = options.buttons) === null || _options$buttons === void 0 || (_options$buttons = _options$buttons[buttonName]) === null || _options$buttons === void 0 ? void 0 : _options$buttons.hidden); } var debugObj = { 'force-update': { shortcut: 'Ctrl+Shift+r', action: function action(editor) { editor.update(true); }, hidden: function hidden(options) { return isHidden(options, 'force-update'); } }, 'qs-serialize': { shortcut: 'Alt+Shift+r', action: function action(editor) { var molSerializer = new ketcherCore.MolSerializer(); var molStr = molSerializer.serialize(editor.struct()); var molQs = 'mol=' + encodeURIComponent(molStr).replace(/%20/g, '+'); var qs = document.location.search; document.location.search = !qs ? '?' + molQs : qs.search('mol=') === -1 ? qs + '&' + molQs : qs.replace(/mol=[^&$]*/, molQs); } }, hidden: function hidden(options) { return isHidden(options, 'qs-serialize'); } }; var classes$Q = {"cliparea":"cliparea-module_cliparea__GdPrN"}; function _createForOfIteratorHelper$h(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$i(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray$i(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$i(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$i(o, minLen); } function _arrayLikeToArray$i(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _callSuper$e(t, o, e) { return o = _getPrototypeOf__default["default"](o), _possibleConstructorReturn__default["default"](t, _isNativeReflectConstruct$g() ? Reflect.construct(o, e || [], _getPrototypeOf__default["default"](t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$g() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$g = function _isNativeReflectConstruct() { return !!t; })(); } var ieCb = typeof window !== 'undefined' ? window.clipboardData : {}; var CLIP_AREA_BASE_CLASS = 'cliparea'; var needSkipCopyEvent = false; var ClipArea = function (_Component) { _inherits__default["default"](ClipArea, _Component); function ClipArea(props) { var _this; _classCallCheck__default["default"](this, ClipArea); _this = _callSuper$e(this, ClipArea, [props]); _this.textAreaRef = React.createRef(); return _this; } _createClass__default["default"](ClipArea, [{ key: "componentDidMount", value: function componentDidMount() { var _this2 = this; var el = this.textAreaRef.current; this.target = this.props.target || el.parentNode; this.listeners = { mouseup: function mouseup(event) { if (el === event.target || !isActiveElement(event.target) && _this2.props.focused()) { autoselect(el); } }, mousedown: function mousedown(event) { if (event.shiftKey && !isActiveElement(event.target)) event.preventDefault(); }, copy: function copy(event) { if (!_this2.props.focused()) { return; } if (ketcherCore.isClipboardAPIAvailable()) { _this2.props.onCopy().then(function (data) { if (!data) { return; } _copy(data).then(function () { event.preventDefault(); ketcherCore.notifyCopyCut(); }); }); } else { if (needSkipCopyEvent) { needSkipCopyEvent = false; return; } needSkipCopyEvent = true; _this2.props.onCopy().then(function (data) { addEventListener('copy', function (evt) { legacyCopy(evt.clipboardData, data); evt.preventDefault(); }, { once: true }); document.execCommand('copy'); }); event.preventDefault(); } }, cut: function () { var _cut = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee(event) { var data; return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: if (_this2.props.focused()) { _context.next = 2; break; } return _context.abrupt("return"); case 2: if (ketcherCore.isClipboardAPIAvailable()) { _this2.props.onCut().then(function (data) { if (!data) { return; } _copy(data).then(function () { event.preventDefault(); ketcherCore.notifyCopyCut(); }); }); } else { data = _this2.props.onLegacyCut(); if (data) { legacyCopy(event.clipboardData, data); } event.preventDefault(); } case 3: case "end": return _context.stop(); } }, _callee); })); function cut(_x) { return _cut.apply(this, arguments); } return cut; }(), paste: function paste(event) { if (!_this2.props.focused()) { return; } if (ketcherCore.isClipboardAPIAvailable()) { navigator.clipboard.read().then(function (data) { if (!data) { return; } _this2.props.onPaste(data).then(function () { event.preventDefault(); ketcherCore.notifyRequestCompleted(); }); }); } else { var data = legacyPaste(event.clipboardData, _this2.props.formats); if (data) { _this2.props.onLegacyPaste(data); } event.preventDefault(); } }, keydown: function () { var _keydown = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee2(event) { var _navigator$clipboard, clipboardData, data, _window$ketcher$edito, _window$ketcher$edito2; return _regeneratorRuntime__default["default"].wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: if (!(!_this2.props.focused() || !_this2.props.onPaste)) { _context2.next = 2; break; } return _context2.abrupt("return"); case 2: if (!(ketcherCore.isControlKey(event) && event.altKey && event.code === 'KeyV')) { _context2.next = 14; break; } if (!((_navigator$clipboard = navigator.clipboard) !== null && _navigator$clipboard !== void 0 && _navigator$clipboard.read)) { _context2.next = 13; break; } _context2.next = 6; return navigator.clipboard.read(); case 6: clipboardData = _context2.sent; _context2.next = 9; return pasteByKeydown(clipboardData); case 9: data = _context2.sent; if (data) { _this2.props.onPaste(data, true); } _context2.next = 14; break; case 13: (_window$ketcher$edito = (_window$ketcher$edito2 = window.ketcher.editor).errorHandler) === null || _window$ketcher$edito === void 0 || _window$ketcher$edito.call(_window$ketcher$edito2, "Your browser doesn't support pasting clipboard content via Ctrl-Alt-V. Please use Google Chrome browser or load SMARTS structure from .smarts file instead."); case 14: case "end": return _context2.stop(); } }, _callee2); })); function keydown(_x2) { return _keydown.apply(this, arguments); } return keydown; }() }; Object.keys(this.listeners).forEach(function (en) { _this2.target.addEventListener(en, _this2.listeners[en]); }); } }, { key: "shouldComponentUpdate", value: function shouldComponentUpdate() { return false; } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this3 = this; Object.keys(this.listeners).forEach(function (en) { _this3.target.removeEventListener(en, _this3.listeners[en]); }); } }, { key: "render", value: function render() { return jsxRuntime.jsx("textarea", { ref: this.textAreaRef, className: clsx__default["default"](CLIP_AREA_BASE_CLASS, classes$Q.cliparea), contentEditable: true, autoFocus: true , suppressContentEditableWarning: true }); } }]); return ClipArea; }(React.Component); function isActiveElement(el) { if (el.tagName === 'INPUT' && el.type === 'button') return false; return ['INPUT', 'SELECT', 'TEXTAREA', 'OPTION', 'LABEL'].includes(el.tagName); } function autoselect(cliparea) { cliparea.value = ' '; cliparea.select(); } function _copy(_x3) { return _copy2.apply(this, arguments); } function _copy2() { _copy2 = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee3(data) { var clipboardItemData, clipboardItem, textData; return _regeneratorRuntime__default["default"].wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: _context3.prev = 0; clipboardItemData = {}; Object.keys(data).forEach(function (mimeType) { var mimeTypeToSet = mimeType === 'text/plain' ? mimeType : "web ".concat(mimeType); clipboardItemData[mimeTypeToSet] = Promise.resolve(new Blob([data[mimeType]], { type: mimeTypeToSet })); }); clipboardItem = new ClipboardItem(clipboardItemData); if (!(clipboardItem.presentationStyle && clipboardItem.presentationStyle === 'unspecified')) { _context3.next = 11; break; } if (!navigator.clipboard.writeText) { _context3.next = 9; break; } textData = data['text/plain'] || JSON.stringify(data); _context3.next = 9; return navigator.clipboard.writeText(textData); case 9: _context3.next = 13; break; case 11: _context3.next = 13; return navigator.clipboard.write([clipboardItem]); case 13: _context3.next = 19; break; case 15: _context3.prev = 15; _context3.t0 = _context3["catch"](0); ketcherCore.KetcherLogger.error('cliparea.jsx::copy', _context3.t0); case 19: case "end": return _context3.stop(); } }, _callee3, null, [[0, 15]]); })); return _copy2.apply(this, arguments); } function legacyCopy(clipboardData, data) { if (!clipboardData && ieCb) { ieCb.setData('text', data['text/plain']); } else { var curFmt = null; clipboardData.setData('text/plain', data['text/plain']); try { Object.keys(data).forEach(function (fmt) { curFmt = fmt; clipboardData.setData(fmt, data[fmt]); }); } catch (e) { } } } function legacyPaste(cb, formats) { var data = {}; if (!cb && ieCb) { data['text/plain'] = ieCb.getData('text'); } else { data['text/plain'] = cb.getData('text/plain'); data = formats.reduce(function (res, fmt) { var d = cb.getData(fmt); if (d) res[fmt] = d; return res; }, data); } return data; } function pasteByKeydown(_x4) { return _pasteByKeydown.apply(this, arguments); } function _pasteByKeydown() { _pasteByKeydown = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee4(clipboardData) { var data, _iterator, _step, item, textPlain; return _regeneratorRuntime__default["default"].wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: data = {}; if (!(!clipboardData && ieCb)) { _context4.next = 5; break; } data['text/plain'] = ieCb.getData('text'); _context4.next = 26; break; case 5: _iterator = _createForOfIteratorHelper$h(clipboardData); _context4.prev = 6; _iterator.s(); case 8: if ((_step = _iterator.n()).done) { _context4.next = 18; break; } item = _step.value; _context4.next = 12; return item.getType('text/plain'); case 12: textPlain = _context4.sent; _context4.next = 15; return textPlain.text(); case 15: data['text/plain'] = _context4.sent; case 16: _context4.next = 8; break; case 18: _context4.next = 23; break; case 20: _context4.prev = 20; _context4.t0 = _context4["catch"](6); _iterator.e(_context4.t0); case 23: _context4.prev = 23; _iterator.f(); return _context4.finish(23); case 26: return _context4.abrupt("return", data); case 27: case "end": return _context4.stop(); } }, _callee4, null, [[6, 20, 23, 26]]); })); return _pasteByKeydown.apply(this, arguments); } var actions = ['cut', 'copy', 'paste']; function exec(action) { var enabled = document.queryCommandSupported(action); if (enabled) { try { enabled = document.execCommand(action) || window.ClipboardEvent || ieCb; } catch (e) { ketcherCore.KetcherLogger.error('cliparea.jsx::exec', e); enabled = false; } } return enabled; } function ownKeys$1v(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$1v(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1v(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1v(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var MeasurementUnits; (function (MeasurementUnits) { MeasurementUnits["Px"] = "px"; MeasurementUnits["Cm"] = "cm"; MeasurementUnits["Pt"] = "pt"; MeasurementUnits["Inch"] = "inch"; })(MeasurementUnits || (MeasurementUnits = {})); var ImageResolution; (function (ImageResolution) { ImageResolution["high"] = "600"; ImageResolution["low"] = "72"; })(ImageResolution || (ImageResolution = {})); var editor = { resetToSelect: { title: 'Reset to Select Tool', "enum": [true, 'paste', false], enumNames: ['on', 'After Paste', 'off'], "default": 'paste' }, rotationStep: { title: 'Rotation Step, º', type: 'integer', minimum: 1, maximum: 90, "default": 15 } }; var render = { showValenceWarnings: { title: 'Show valence warnings', type: 'boolean', description: 'slider', "default": true }, atomColoring: { title: 'Atom coloring', type: 'boolean', description: 'slider', "default": true }, showStereoFlags: { title: 'Show the Stereo flags', type: 'boolean', description: 'slider', "default": true }, stereoLabelStyle: { title: "Label display at\xA0stereogenic\xA0centers", "enum": [ketcherCore.StereLabelStyleType.IUPAC, ketcherCore.StereLabelStyleType.Classic, ketcherCore.StereLabelStyleType.On, ketcherCore.StereLabelStyleType.Off], enumNames: ['IUPAC style', 'Classic', 'On', 'Off'], "default": ketcherCore.StereLabelStyleType.IUPAC }, colorOfAbsoluteCenters: { title: ' Absolute Center color', type: 'string', "default": '#ff0000' }, colorOfAndCenters: { title: 'AND Centers color', type: 'string', "default": '#0000cd' }, colorOfOrCenters: { title: 'OR Centers color', type: 'string', "default": '#228b22' }, colorStereogenicCenters: { title: 'Color stereogenic centers', "enum": [ketcherCore.StereoColoringType.LabelsOnly, ketcherCore.StereoColoringType.BondsOnly, ketcherCore.StereoColoringType.LabelsAndBonds, ketcherCore.StereoColoringType.Off], enumNames: ['Labels Only', 'Bonds Only', 'Labels And Bonds', 'Off'], "default": ketcherCore.StereoColoringType.LabelsOnly }, autoFadeOfStereoLabels: { title: 'Auto fade And/Or center labels', type: 'boolean', description: 'slider', "default": true }, absFlagLabel: { title: 'Text of Absolute flag', type: 'string', "default": 'ABS' }, andFlagLabel: { title: 'Text of AND flag', type: 'string', "default": 'AND Enantiomer' }, mixedFlagLabel: { title: 'Text of Mixed flag', type: 'string', "default": 'Mixed' }, ignoreChiralFlag: { title: 'Ignore the chiral flag', type: 'boolean', description: 'slider', "default": false }, orFlagLabel: { title: 'Text of OR flag', type: 'string', "default": 'OR Enantiomer' }, font: { title: 'Font', type: 'string', "default": '30px Arial' }, fontsz: { title: 'Font size', type: 'number', "default": 13, minimum: 0.1, maximum: 96 }, fontszUnit: { title: 'Font size unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, fontszsub: { title: 'Sub font size', type: 'number', "default": 13, minimum: 0.1, maximum: 96 }, fontszsubUnit: { title: 'Sub font size unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, carbonExplicitly: { title: 'Display carbon explicitly', type: 'boolean', description: 'slider', "default": false }, showCharge: { title: 'Display charge', type: 'boolean', description: 'slider', "default": true }, showValence: { title: 'Display valence', type: 'boolean', description: 'slider', "default": true }, showHydrogenLabels: { title: 'Show hydrogen labels', "enum": Object.values(ketcherCore.ShowHydrogenLabels), enumNames: Object.values(ketcherCore.ShowHydrogenLabelNames), "default": ketcherCore.ShowHydrogenLabels.TerminalAndHetero }, aromaticCircle: { title: 'Aromatic Bonds as circle', type: 'boolean', description: 'slider', "default": true }, bondSpacing: { title: 'Bond spacing', type: 'integer', "default": 15, minimum: 1, maximum: 100 }, bondThickness: { title: 'Bond thickness', type: 'number', "default": ketcherCore.defaultBondThickness, minimum: 0.1, maximum: 96 }, bondThicknessUnit: { title: 'Bond thickness unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, stereoBondWidth: { title: 'Stereo (Wedge) bond width', type: 'number', "default": 6, minimum: 0.1, maximum: 96 }, stereoBondWidthUnit: { title: 'Stereo (Wedge) bond width unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, bondLength: { title: 'Bond length', type: 'number', "default": 40, minimum: 0.1, maximum: 1000 }, bondLengthUnit: { title: 'Bond length unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, reactionComponentMarginSize: { title: 'Reaction component margin size', type: 'number', "default": 20, minimum: 0.1, maximum: 1000 }, reactionComponentMarginSizeUnit: { title: 'Reaction component margin size unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, hashSpacing: { title: 'Hash spacing', type: 'number', "default": 1.2, minimum: 0.1, maximum: 1000 }, hashSpacingUnit: { title: 'Hash spacing unit', "enum": Object.values(MeasurementUnits), enumNames: Object.values(MeasurementUnits), "default": MeasurementUnits.Px }, imageResolution: { title: 'Image resolution', "enum": Object.values(ImageResolution), enumNames: Object.keys(ImageResolution), "default": ImageResolution.low } }; var server = { 'dearomatize-on-load': { title: 'dearomatize-on-load', type: 'boolean', description: 'slider', "default": false }, 'smart-layout': { title: 'Smart-layout', type: 'boolean', description: 'slider', "default": true }, ignoreChiralFlag: { title: 'Ignore the chiral flag', type: 'boolean', description: 'slider', "default": false }, 'ignore-stereochemistry-errors': { title: 'Ignore stereochemistry errors', type: 'boolean', description: 'slider', "default": true }, 'mass-skip-error-on-pseudoatoms': { title: 'Ignore pseudoatoms at mass', type: 'boolean', description: 'slider', "default": false }, 'gross-formula-add-rsites': { title: 'Add Rsites at mass calculation', type: 'boolean', description: 'slider', "default": true }, 'gross-formula-add-isotopes': { title: "Add Isotopes at\xA0mass\xA0calculation", type: 'boolean', description: 'slider', "default": true } }; var SERVER_OPTIONS = Object.keys(server); var debug = { showAtomIds: { title: 'Show atom Ids', type: 'boolean', description: 'slider', "default": false }, showBondIds: { title: 'Show bonds Ids', type: 'boolean', description: 'slider', "default": false }, showHalfBondIds: { title: 'Show half bonds Ids', type: 'boolean', description: 'slider', "default": false }, showLoopIds: { title: 'Show loop Ids', type: 'boolean', description: 'slider', "default": false } }; var miew = { miewMode: { title: 'Display mode', "enum": ['LN', 'BS', 'LC'], enumNames: ['Lines', 'Balls and Sticks', 'Licorice'], "default": 'LN' }, miewTheme: { title: 'Background color', "enum": ['light', 'dark'], enumNames: ['Light', 'Dark'], "default": 'light' }, miewAtomLabel: { title: 'Label coloring', "enum": ['no', 'bright', 'blackAndWhite', 'black'], enumNames: ['No', 'Bright', 'Black and White', 'Black'], "default": 'bright' } }; var MIEW_OPTIONS = Object.keys(miew); var optionsSchema = { title: 'Settings', type: 'object', required: [], properties: _objectSpread$1v(_objectSpread$1v(_objectSpread$1v(_objectSpread$1v(_objectSpread$1v({}, editor), render), server), debug), miew) }; function getDefaultOptions() { if (!optionsSchema.properties) return {}; return Object.keys(optionsSchema.properties).reduce(function (res, prop) { res[prop] = optionsSchema.properties[prop]["default"]; return res; }, {}); } function validation(settings) { if (_typeof__default["default"](settings) !== 'object' || settings === null) return null; var ajv = new Ajv__default["default"]({ allErrors: true, keywords: [{ keyword: 'enumNames', schemaType: 'array' }] }); var validate = ajv.compile(optionsSchema); validate(settings); var errors = validate.errors || []; var errorsProps = errors.map(function (el) { return el.instancePath.slice(1); }); return Object.keys(settings).reduce(function (res, prop) { if (!optionsSchema.properties) return res; if (optionsSchema.properties[prop] && errorsProps.indexOf(prop) === -1) res[prop] = settings[prop]; return res; }, {}); } var storage = { warningMessage: 'Your changes will be lost after the tab closing. See Help (Note 2).', isAvailable: function isAvailable() { try { var _storage = global.localStorage; return _storage; } catch (e) { ketcherCore.KetcherLogger.error('storage-ext.js::storage::isAvailable', e); return false; } }, getItem: function getItem(key) { var item = null; try { item = JSON.parse(localStorage.getItem(key)); } catch (e) { ketcherCore.KetcherLogger.error('storage-ext.js::storage::getItem', e); } return item; }, setItem: function setItem(key, data) { var isSet = null; try { localStorage.setItem(key, JSON.stringify(data)); isSet = true; } catch (e) { ketcherCore.KetcherLogger.error('storage-ext.js::storage::setItem', e); isSet = false; } return isSet; } }; var templatesRawData$2 = "alpha-D-Allopyranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 12 12 0 1 0 999 V2000\n -2.4110 3.5743 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.4110 1.6992 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.2304 0.7587 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -6.0499 1.6991 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.2360 3.5743 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -6.8478 2.9800 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.3208 3.1152 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.3208 2.1638 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.2360 1.6991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -5.1456 2.1636 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -5.1456 3.1151 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -6.0499 3.5741 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 6 12 1 0 0 0\n 11 5 1 0 0 0\n 5 7 1 0 0 0\n 7 8 1 0 0 0\n 8 9 1 0 0 0\n 9 10 1 0 0 0\n 10 11 1 0 0 0\n 11 12 1 1 0 0\n 7 1 1 6 0 0\n 8 2 1 6 0 0\n 9 3 1 6 0 0\n 10 4 1 6 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n> <atomid>\n0\n\n> <bondid>\n0\n\n$$$$\nalpha-D-Altropyranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 12 12 0 1 0 999 V2000\n -0.9910 2.2903 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -0.9910 0.7936 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.2875 0.0452 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.5799 0.7935 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.2834 2.2903 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.1462 1.8062 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -1.6372 1.9161 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -1.6372 1.1678 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.2834 0.7935 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.9337 1.1677 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.9337 1.9160 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.5799 2.2902 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 6 12 1 0 0 0\n 11 5 1 0 0 0\n 5 7 1 0 0 0\n 7 8 1 0 0 0\n 8 9 1 0 0 0\n 9 10 1 0 0 0\n 10 11 1 0 0 0\n 11 12 1 1 0 0\n 7 1 1 6 0 0\n 8 2 1 1 0 0\n 9 3 1 6 0 0\n 10 4 1 6 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n> <atomid>\n0\n\n> <bondid>\n0\n\n$$$$\nalpha-D-Arabinofuranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 10 10 0 1 0 999 V2000\n -1.9332 3.1927 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.5926 1.1426 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.7765 1.1387 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.7048 3.4871 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -6.0588 2.4002 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8825 2.8828 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.1801 1.9478 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.1909 1.9478 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.5142 2.8976 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -5.4573 3.1978 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 9 4 1 0 0 0\n 9 8 1 0 0 0\n 4 6 1 0 0 0\n 8 7 1 0 0 0\n 6 7 1 0 0 0\n 9 10 1 1 0 0\n 10 5 1 0 0 0\n 6 1 1 6 0 0\n 7 2 1 1 0 0\n 8 3 1 6 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n> <atomid>\n0\n\n> <bondid>\n0\n\n$$$$\nalpha-D-Arabinopyranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 10 10 0 1 0 999 V2000\n 15.5611 -5.2999 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 15.5611 -7.3001 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 13.8228 -8.3002 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 12.0958 -7.3001 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 13.8228 -5.2999 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 14.6920 -5.8000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 14.6920 -6.7999 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 13.8228 -7.3001 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 12.9648 -6.7999 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 12.9648 -5.8000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 5 10 1 0 0 0\n 10 9 1 0 0 0\n 9 8 1 0 0 0\n 8 7 1 0 0 0\n 7 6 1 0 0 0\n 6 5 1 0 0 0\n 6 1 1 6 0 0\n 7 2 1 1 0 0\n 8 3 1 6 0 0\n 9 4 1 6 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n$$$$\nalpha-D-Erythrofuranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 8 8 0 1 0 999 V2000\n -2.3742 2.6418 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8682 1.1059 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.4960 1.1030 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.7013 2.8623 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.0854 2.4096 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.3125 1.7091 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.0613 1.7091 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.3035 2.4207 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 8 4 1 0 0 0\n 8 7 1 0 0 0\n 4 5 1 0 0 0\n 7 6 1 0 0 0\n 5 6 1 0 0 0\n 5 1 1 6 0 0\n 6 2 1 6 0 0\n 7 3 1 6 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n> <atomid>\n0\n\n> <bondid>\n0\n\n$$$$\nalpha-D-Galactopyranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 12 12 0 1 0 999 V2000\n -1.5577 2.5236 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -1.5577 1.0270 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8542 0.2785 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.1466 1.0269 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8543 2.5236 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.7171 2.0395 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.2039 2.1495 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.2039 1.4011 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8543 1.0269 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.5004 1.4010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.5004 2.1494 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.1466 2.5235 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 6 12 1 0 0 0\n 11 5 1 0 0 0\n 5 7 1 0 0 0\n 7 8 1 0 0 0\n 8 9 1 0 0 0\n 9 10 1 0 0 0\n 10 11 1 0 0 0\n 11 12 1 1 0 0\n 7 1 1 6 0 0\n 8 2 1 6 0 0\n 9 3 1 1 0 0\n 10 4 1 1 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n$$$$\nalpha-D-Glucopyranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 12 12 0 1 0 999 V2000\n -2.1744 2.8153 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.1744 1.3186 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.4708 0.5702 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.7632 1.3185 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.4709 2.8153 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -5.3337 2.3312 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8206 2.4411 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.8206 1.6928 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.4709 1.3185 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.1170 1.6927 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.1170 2.4410 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.7632 2.8152 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 6 12 1 0 0 0\n 11 5 1 0 0 0\n 5 7 1 0 0 0\n 7 8 1 0 0 0\n 8 9 1 0 0 0\n 9 10 1 0 0 0\n 10 11 1 0 0 0\n 11 12 1 1 0 0\n 7 1 1 6 0 0\n 8 2 1 6 0 0\n 9 3 1 1 0 0\n 10 4 1 6 0 0\nM END\n> <group>\nalpha-D-Sugars\n\n$$$$\nalpha-D-Gulopyranose\n Ketcher 11161713142D 1 1.00000 0.00000 0\n\n 12 12 0 1 0 999 V2000\n -2.1119 2.8570 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.1119 1.3603 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.4083 0.6119 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -4.7007 1.3602 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -3.4084 2.8570 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -5.2712 2.3728 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n -2.7581 2.4828 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -2.7581 1.7345 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -3.4084 1.3602 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.0545 1.7344 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.0545 2.4827 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n -4.7007 2.8569 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n