├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── frame-nlp-service ├── Dockerfile ├── README.md ├── app │ ├── __init__.py │ ├── abstractive_summarizer │ │ ├── __init__.py │ │ └── abstractive_summarizer.py │ ├── bidaf-model-2017.09.15-charpad.tar.gz │ ├── main.py │ ├── question_answer_model │ │ ├── __init__.py │ │ └── question_answer_model.py │ ├── requirements.txt │ └── uwsgi.ini ├── docker-compose.override.yml └── docker-compose.yml ├── frame-website ├── about.html ├── css │ ├── homepage.css │ └── slider.css ├── docs.html ├── download.html ├── iconfonts │ ├── flaticon.css │ ├── flaticon.eot │ ├── flaticon.svg │ ├── flaticon.ttf │ └── flaticon.woff ├── images │ ├── Frame-animated-demo-01-14-2019.gif │ ├── banner.png │ ├── frame_screenshot_01-21-2019_alice_in_wonderland_information_extraction.png │ ├── frame_screenshot_01-21-2019_cryptocurrency_analysis.png │ ├── frame_screenshot_01-21-2019_sicko_mode_visualization.png │ ├── frame_screenshot_01-21-2019_this_is_water_summarization.png │ ├── framed_video_animation_demo.mp4 │ ├── liveforms.png │ ├── scripteden-logo-g.png │ └── totoro-horizontal.jpg ├── index.html ├── js │ ├── homepage.js │ └── slideshow.js └── semantic-ui │ ├── semantic.css │ ├── semantic.js │ ├── semantic.min.css │ └── semantic.min.js ├── frame ├── .babelrc ├── .eslintignore ├── .eslintrc.json ├── .flowconfig ├── .gitattributes ├── .jsbeautifyrc ├── .vscode │ ├── launch.json │ └── settings.json ├── README.md ├── custom_node_modules │ ├── medium-draft │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── example │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── index.html │ │ ├── lib │ │ │ ├── basic.css │ │ │ ├── components │ │ │ │ ├── LinkEditComponent.js │ │ │ │ ├── addbutton.js │ │ │ │ ├── blocks │ │ │ │ │ ├── atomic.js │ │ │ │ │ ├── blockquotecaption.js │ │ │ │ │ ├── break.js │ │ │ │ │ ├── caption.js │ │ │ │ │ ├── image.js │ │ │ │ │ ├── text.js │ │ │ │ │ └── todo.js │ │ │ │ ├── blocktoolbar.js │ │ │ │ ├── customrenderer.js │ │ │ │ ├── entities │ │ │ │ │ └── link.js │ │ │ │ ├── inlinetoolbar.js │ │ │ │ ├── sides │ │ │ │ │ ├── break.js │ │ │ │ │ └── image.js │ │ │ │ ├── stylebutton.js │ │ │ │ └── toolbar.js │ │ │ ├── createEditor.js │ │ │ ├── editor.js │ │ │ ├── exporter.js │ │ │ ├── handlers │ │ │ │ ├── blockRenderMap.js │ │ │ │ ├── blockRendererFn.js │ │ │ │ ├── blockStyleFn.js │ │ │ │ ├── handleBeforeInput.js │ │ │ │ ├── handleKeyCommand.js │ │ │ │ ├── handlePastedText.js │ │ │ │ ├── handleReturn.js │ │ │ │ ├── index.js │ │ │ │ ├── keyBindingFn.js │ │ │ │ ├── onTab.js │ │ │ │ └── onUpArrow.js │ │ │ ├── importer.js │ │ │ ├── index.css │ │ │ ├── index.js │ │ │ ├── model │ │ │ │ ├── content.js │ │ │ │ └── index.js │ │ │ └── util │ │ │ │ ├── beforeinput.js │ │ │ │ ├── blockStyleFn.js │ │ │ │ ├── constants.js │ │ │ │ ├── customstylemap.js │ │ │ │ ├── index.js │ │ │ │ ├── keybinding.js │ │ │ │ └── rendermap.js │ │ ├── package.json │ │ └── rendered.html │ └── node-sumbasic │ │ ├── LICENSE │ │ ├── README.md │ │ ├── package.json │ │ └── src │ │ ├── demo.js │ │ └── index.js ├── package-lock.json ├── package.json ├── public │ └── electron.js ├── src │ ├── assets │ │ ├── css │ │ │ ├── all.css │ │ │ ├── all.min.css │ │ │ ├── brands.css │ │ │ ├── brands.min.css │ │ │ ├── fontawesome.css │ │ │ ├── fontawesome.min.css │ │ │ ├── quill.snow.css │ │ │ ├── regular.css │ │ │ ├── regular.min.css │ │ │ ├── solid.css │ │ │ ├── solid.min.css │ │ │ ├── svg-with-js.css │ │ │ ├── svg-with-js.min.css │ │ │ ├── v4-shims.css │ │ │ └── v4-shims.min.css │ │ ├── electron.png │ │ ├── flow.png │ │ ├── github.png │ │ ├── js │ │ │ ├── all.js │ │ │ ├── all.min.js │ │ │ ├── brands.js │ │ │ ├── brands.min.js │ │ │ ├── fontawesome.js │ │ │ ├── fontawesome.min.js │ │ │ ├── regular.js │ │ │ ├── regular.min.js │ │ │ ├── solid.js │ │ │ ├── solid.min.js │ │ │ ├── v4-shims.js │ │ │ └── v4-shims.min.js │ │ ├── react.svg │ │ ├── redux.svg │ │ ├── semantic-ui-react.png │ │ ├── webfonts │ │ │ ├── fa-brands-400.eot │ │ │ ├── fa-brands-400.svg │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-brands-400.woff │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.eot │ │ │ ├── fa-regular-400.svg │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.eot │ │ │ ├── fa-solid-900.svg │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-solid-900.woff │ │ │ └── fa-solid-900.woff2 │ │ └── webpack.svg │ ├── components │ │ ├── Analyzer │ │ │ ├── Analyzer.jsx │ │ │ ├── Analyzer.scss │ │ │ └── tabStyle.css │ │ ├── App │ │ │ ├── App.jsx │ │ │ └── App.scss │ │ ├── Ask │ │ │ ├── Ask.jsx │ │ │ └── Ask.scss │ │ ├── AskMain │ │ │ ├── AskMain.jsx │ │ │ └── AskMain.scss │ │ ├── Brand │ │ │ ├── Brand.jsx │ │ │ └── Brand.scss │ │ ├── EntryCreate │ │ │ ├── EntryCreate.jsx │ │ │ └── EntryCreate.scss │ │ ├── EntryEditForm │ │ │ ├── EntryEditForm.jsx │ │ │ └── EntryEditForm.scss │ │ ├── FJSONEditor │ │ │ ├── FJSONEditor.jsx │ │ │ └── FJSONEditor.scss │ │ ├── Home │ │ │ ├── Home.jsx │ │ │ └── Home.scss │ │ ├── MainMenu │ │ │ ├── MainMenu.jsx │ │ │ └── MainMenu.scss │ │ ├── Notepad │ │ │ ├── Notepad.jsx │ │ │ └── Notepad.scss │ │ ├── SearchLibrary │ │ │ ├── SearchLibrary.jsx │ │ │ └── SearchLibrary.scss │ │ ├── Settings │ │ │ ├── Settings.jsx │ │ │ └── Settings.scss │ │ ├── VisualizeLibrary │ │ │ ├── VisualizeLibrary.jsx │ │ │ └── VisualizeLibrary.scss │ │ ├── Visualizer │ │ │ ├── Visualizer.jsx │ │ │ └── Visualizer.scss │ │ └── vendor │ │ │ ├── basic.scss │ │ │ ├── components │ │ │ ├── LinkEditComponent.js │ │ │ ├── addbutton.js │ │ │ ├── addbutton.scss │ │ │ ├── blocks │ │ │ │ ├── atomic.js │ │ │ │ ├── atomic.scss │ │ │ │ ├── blockquotecaption.js │ │ │ │ ├── blockquotecaption.scss │ │ │ │ ├── break.js │ │ │ │ ├── caption.js │ │ │ │ ├── caption.scss │ │ │ │ ├── image.js │ │ │ │ ├── image.scss │ │ │ │ ├── text.js │ │ │ │ ├── text.scss │ │ │ │ ├── todo.js │ │ │ │ └── todo.scss │ │ │ ├── blocktoolbar.js │ │ │ ├── customrenderer.js │ │ │ ├── entities │ │ │ │ └── link.js │ │ │ ├── inlinetoolbar.js │ │ │ ├── sides │ │ │ │ ├── break.js │ │ │ │ └── image.js │ │ │ ├── stylebutton.js │ │ │ ├── toolbar.js │ │ │ └── toolbar.scss │ │ │ ├── editor.js │ │ │ ├── example.js │ │ │ ├── exporter.js │ │ │ ├── importer.js │ │ │ ├── index.js │ │ │ ├── index.scss │ │ │ ├── model │ │ │ ├── content.js │ │ │ ├── content.spec.js │ │ │ ├── index.js │ │ │ └── index.spec.js │ │ │ └── util │ │ │ ├── beforeinput.js │ │ │ ├── beforeinput.spec.js │ │ │ ├── blockStyleFn.js │ │ │ ├── blockStyleFn.spec.js │ │ │ ├── constants.js │ │ │ ├── constants.spec.js │ │ │ ├── customstylemap.js │ │ │ ├── index.js │ │ │ ├── keybinding.js │ │ │ ├── rendermap.js │ │ │ └── rendermap.spec.js │ ├── data │ │ ├── config.json │ │ └── libraries_collections │ │ │ └── default.json │ ├── index.js │ ├── lib │ │ ├── custom-vendor │ │ │ ├── node-content-renderer.js │ │ │ ├── node-content-renderer.scss │ │ │ ├── react-sortable-tree-style.css │ │ │ ├── tree-node-renderer.js │ │ │ └── tree-node-renderer.scss │ │ └── node-nlp-service.js │ └── utils │ │ ├── create-db.js │ │ ├── entries-traversal.js │ │ ├── generate-uuid.js │ │ ├── get-timestamp.js │ │ ├── load-db.js │ │ ├── register-service-worker.js │ │ ├── replace-entry.js │ │ ├── save-db.js │ │ ├── session-state.js │ │ ├── translate-html.js │ │ └── vendor │ │ ├── classnames.js │ │ ├── default-handlers.js │ │ ├── dnd-manager.js │ │ ├── generic-utils.js │ │ ├── generic-utils.test.js │ │ ├── memoized-tree-data-utils.js │ │ ├── memoized-tree-data-utils.test.js │ │ ├── tree-data-utils.js │ │ └── tree-data-utils.test.js ├── webpack.common.js ├── webpack.config.eslint.js ├── webpack.dev.electron.js ├── webpack.dev.js ├── webpack.prod.electron.js ├── webpack.prod.js └── yarn.lock └── screenshots ├── frame_screenshot_01-21-2019_alice_in_wonderland_information_extraction.png ├── frame_screenshot_01-21-2019_cryptocurrency_analysis.png ├── frame_screenshot_01-21-2019_sicko_mode_visualization.png ├── frame_screenshot_01-21-2019_this_is_water_summarization.png └── framed_video_animation_demo.gif /.gitattributes: -------------------------------------------------------------------------------- 1 | *.tar filter=lfs diff=lfs merge=lfs -text 2 | *.tar.gz filter=lfs diff=lfs merge=lfs -text 3 | dist/* linguist-vendored=true 4 | node_modules/* linguist-vendored=true 5 | lib/* linguist-vendored=true 6 | output/* linguist-vendored=true 7 | react-sortable-tree-style.css linguist-vendored=true 8 | *.js linguist-vendored=false 9 | *.gz filter=lfs diff=lfs merge=lfs -text 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from 33 | a template 34 | # before PyInstaller builds the exe, so as to inject 35 | date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # celery beat schedule file 89 | celerybeat-schedule 90 | 91 | # SageMath parsed files 92 | *.sage.py 93 | 94 | # Environments 95 | .env 96 | .venv 97 | env/ 98 | venv/ 99 | ENV/ 100 | env.bak/ 101 | venv.bak/ 102 | 103 | # Spyder project settings 104 | .spyderproject 105 | .spyproject 106 | 107 | # Rope project settings 108 | .ropeproject 109 | 110 | # mkdocs documentation 111 | /site 112 | 113 | # mypy 114 | .mypy_cache/ 115 | .dmypy.json 116 | dmypy.json 117 | 118 | # Pyre type checker 119 | .pyre/ 120 | 121 | 122 | # Node 123 | 124 | # Logs 125 | logs 126 | *.log 127 | npm-debug.log* 128 | yarn-debug.log* 129 | yarn-error.log* 130 | 131 | # Runtime data 132 | pids 133 | *.pid 134 | *.seed 135 | *.pid.lock 136 | 137 | # Directory for instrumented libs generated by 138 | jscoverage/JSCover 139 | lib-cov 140 | 141 | # Coverage directory used by tools like istanbul 142 | coverage 143 | 144 | # nyc test coverage 145 | .nyc_output 146 | 147 | # Grunt intermediate storage 148 | (https://gruntjs.com/creating-plugins#storing-task-files) 149 | .grunt 150 | 151 | # Bower dependency directory (https://bower.io/) 152 | bower_components 153 | 154 | # node-waf configuration 155 | .lock-wscript 156 | 157 | # Compiled binary addons 158 | (https://nodejs.org/api/addons.html) 159 | build/Release 160 | 161 | # Dependency directories 162 | node_modules/ 163 | jspm_packages/ 164 | 165 | # TypeScript v1 declaration files 166 | typings/ 167 | 168 | # Optional npm cache directory 169 | .npm 170 | 171 | # Optional eslint cache 172 | .eslintcache 173 | 174 | # Optional REPL history 175 | .node_repl_history 176 | 177 | # Output of 'npm pack' 178 | *.tgz 179 | 180 | # Yarn Integrity file 181 | .yarn-integrity 182 | 183 | # dotenv environment variables file 184 | .env 185 | 186 | # parcel-bundler cache (https://parceljs.org/) 187 | .cache 188 | 189 | # next.js build output 190 | .next 191 | 192 | # nuxt.js build output 193 | .nuxt 194 | 195 | # vuepress build output 196 | .vuepress/dist 197 | 198 | # Serverless directories 199 | .serverless/ 200 | 201 | # FuseBox cache 202 | .fusebox/ 203 | 204 | #DynamoDB Local files 205 | .dynamodb/ 206 | 207 | # Electron 208 | 209 | electron/ 210 | 211 | 212 | 213 | # Other web stuff 214 | 215 | output/ 216 | dist/ 217 | 218 | 219 | # Virtualenv 220 | 221 | frame-nlp-service-venv 222 | 223 | nohup.out 224 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 Johnny Dunn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /frame-nlp-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.7 2 | 3 | ENV STATIC_INDEX 1 4 | 5 | # Set the working directory to /app 6 | WORKDIR /app 7 | 8 | COPY ./app /app 9 | 10 | # Dependencies 11 | RUN pip install --upgrade pip && pip install --trusted-host pypi.python.org -r requirements.txt && python -m spacy download en 12 | 13 | # Make port 80 available to the world outside this container 14 | EXPOSE 80 15 | 16 | # Define environment variable 17 | ENV NAME World 18 | 19 | # Run app.py when the container launches 20 | CMD ["python", "main.py"] -------------------------------------------------------------------------------- /frame-nlp-service/README.md: -------------------------------------------------------------------------------- 1 | # Frame (NLP Service - Python Backend) 2 | 3 | Frame's abstractive summarization and answer prediction features are done in a Python environment running PyTorch, with an API exposed (by default to all traffic). Frame is still fully functional without the Python backend, and most of the analysis and all visualizations are rendered in the UI files. 4 | 5 | By default, the API will be exposed to port 80, and if run through Docker, served with Nginx. 6 | 7 | # Installation / Running 8 | 9 | ## Virtualenv 10 | 11 | (Virtualenv) 12 | 13 | To install all the packages run: 14 | ```sh 15 | $ pip3 install -r requirements.txt 16 | ``` 17 | You may need to install PyTorch and AllenNLP and a few other dependencies manually (depending on the OS). 18 | 19 | To run Flask API (not recommended unless for testing): 20 | ```sh 21 | $ cd app 22 | $ python3 main.py 23 | ``` 24 | 25 | ## Docker 26 | 27 | The Docker image is configured to automatically serve the Flask API through Nginx. 28 | 29 | To build the Docker image: 30 | 31 | ```sh 32 | $ docker build -t imgname . 33 | ``` 34 | 35 | To run: 36 | 37 | ```sh 38 | $ docker run -d --name mycontainer -p 80:80 imgname 39 | ``` 40 | 41 | # API docs 42 | 43 | Creates abstractive summary of text (str). Returns str. 44 | 45 | ``` 46 | /api/abstractive_summarize 47 | ``` 48 | 49 | Creates abstractive summary of array of texts (items are individually summarized). Returns array. 50 | 51 | ``` 52 | /api/abstractive_summarize_paragraphs 53 | ``` 54 | 55 | Gets an answer to a question asked in natural language. Takes two args, both strs (first is passage text, second is question). Returns str. 56 | 57 | ``` 58 | /api/make_predict 59 | ``` -------------------------------------------------------------------------------- /frame-nlp-service/app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-nlp-service/app/__init__.py -------------------------------------------------------------------------------- /frame-nlp-service/app/abstractive_summarizer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-nlp-service/app/abstractive_summarizer/__init__.py -------------------------------------------------------------------------------- /frame-nlp-service/app/abstractive_summarizer/abstractive_summarizer.py: -------------------------------------------------------------------------------- 1 | from pysummarization.nlpbase.auto_abstractor import AutoAbstractor 2 | from pysummarization.tokenizabledoc.simple_tokenizer import SimpleTokenizer 3 | from pysummarization.abstractabledoc.top_n_rank_abstractor import TopNRankAbstractor 4 | 5 | class AbstractiveSummarizer: 6 | 7 | def __init__(self): 8 | # Object of automatic summarization. 9 | self.auto_abstractor = AutoAbstractor() 10 | # Set tokenizer. 11 | self.auto_abstractor.tokenizable_doc = SimpleTokenizer() 12 | # Set delimiter for making a list of sentence. 13 | self.auto_abstractor.delimiter_list = [".", "\n", "\r\n", "!", "?"] 14 | self.abstractable_doc = TopNRankAbstractor() 15 | return 16 | 17 | def summarize(self, document: str): 18 | result_dict = self.auto_abstractor.summarize(document, self.abstractable_doc) 19 | # print(result_dict) 20 | # for sentence in result_dict["summarize_result"]: 21 | # print(sentence) 22 | return result_dict 23 | 24 | if __name__ != 'main': 25 | abstractive_summarizer = AbstractiveSummarizer() 26 | else: 27 | abstractive_summarizer = AbstractiveSummarizer() 28 | 29 | -------------------------------------------------------------------------------- /frame-nlp-service/app/bidaf-model-2017.09.15-charpad.tar.gz: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fe3045f0e56f5d5da26bbec5553b26f7ee57dc9977a8c9a5bbf733efdcef691b 3 | size 46175392 4 | -------------------------------------------------------------------------------- /frame-nlp-service/app/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify 2 | from flask_cors import CORS 3 | 4 | app = Flask(__name__) 5 | cors = CORS(app) 6 | 7 | from abstractive_summarizer import abstractive_summarizer 8 | from question_answer_model import question_answer_model 9 | 10 | QAModel = question_answer_model.QuestionAnswerModel() 11 | ABSummarizer = abstractive_summarizer.AbstractiveSummarizer() 12 | 13 | HOST = '0.0.0.0' 14 | PORT = '80' 15 | 16 | @app.route("/") 17 | def hello(): 18 | return("Frame NLP Python backend running at " + HOST + ':' + PORT) 19 | 20 | @app.route("/api/abstractive_summarize", methods=['GET', 'POST']) 21 | def abstract(): 22 | # Gets and returs jsonified string 23 | # Builds an abstractive summary of a text 24 | passage = request.get_json() 25 | res = ABSummarizer.summarize(passage) 26 | return jsonify(res) 27 | 28 | @app.route("/api/abstractive_summarize_paragraphs", methods=['GET', 'POST']) 29 | def abstract_paragraphs(): 30 | # Builds abstractive summaries of texts by paragraphs 31 | # Gets and returns jsonified array 32 | paragraphs = request.get_json() 33 | results = [] 34 | for passage in paragraphs: 35 | res = ABSummarizer.summarize(passage) 36 | results.append(res) 37 | return jsonify(results) 38 | 39 | @app.route("/api/make_predict", methods=['GET', 'POST']) 40 | def ask(): 41 | # Gets answer to question in context of a passage of text 42 | # Gets and returns jsonified strings 43 | passage = request.get_json()['passage'] 44 | question = request.get_json()['question'] 45 | res = QAModel.make_predict(passage, question) 46 | return jsonify(res) 47 | 48 | if __name__ == "__main__": 49 | # Only for debugging while developing 50 | app.run(host=HOST, debug=True, port=PORT) -------------------------------------------------------------------------------- /frame-nlp-service/app/question_answer_model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-nlp-service/app/question_answer_model/__init__.py -------------------------------------------------------------------------------- /frame-nlp-service/app/question_answer_model/question_answer_model.py: -------------------------------------------------------------------------------- 1 | from allennlp.predictors.predictor import Predictor 2 | import os 3 | import sys 4 | 5 | from pathlib import Path 6 | data = Path("bidaf-model-2017.09.15-charpad.tar.gz") 7 | 8 | scriptPath = os.path.realpath(os.path.dirname(sys.argv[0])) 9 | 10 | class QuestionAnswerModel: 11 | 12 | def __init__(self): 13 | pass 14 | 15 | def make_predict(self, passage: str, question: str): 16 | # For some reason setting Predictor into a class var was returning bad data from the model, 17 | # so let's make it every time I guess 18 | predictor = Predictor.from_path(data) 19 | # predictor = Predictor.from_path("https://s3-us-west-2.amazonaws.com/allennlp/models/bidaf-model-2017.09.15-charpad.tar.gz") 20 | ans = predictor.predict(passage=passage,question=question) 21 | # print(ans['best_span_str']) 22 | return ans['best_span_str'] 23 | 24 | if __name__ != 'main': 25 | qa_model = QuestionAnswerModel() 26 | else: 27 | qa_model = QuestionAnswerModel() 28 | 29 | -------------------------------------------------------------------------------- /frame-nlp-service/app/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-nlp-service/app/requirements.txt -------------------------------------------------------------------------------- /frame-nlp-service/app/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | module = main 3 | callable = app 4 | -------------------------------------------------------------------------------- /frame-nlp-service/docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | volumes: 5 | - ./app:/app 6 | ports: 7 | - "80:80" 8 | environment: 9 | - FLASK_APP=main.py 10 | - FLASK_DEBUG=1 11 | - 'RUN=flask run --host=0.0.0.0 --port=80' 12 | command: flask run --host=0.0.0.0 --port=80 13 | # Infinite loop, to keep it alive, for debugging 14 | # command: bash -c "while true; do echo 'sleeping...' && sleep 10; done" 15 | -------------------------------------------------------------------------------- /frame-nlp-service/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | build: ./ 5 | -------------------------------------------------------------------------------- /frame-website/css/slider.css: -------------------------------------------------------------------------------- 1 | * {box-sizing:border-box} 2 | 3 | /* Slideshow container */ 4 | .slideshow-container { 5 | max-width: 1000px; 6 | position: relative; 7 | margin: auto; 8 | margin-bottom: -34px; 9 | padding-bottom: 0; 10 | box-shadow: 0 4px 8px 0 rgba(0,0,0,0.12), 11 | 0 2px 4px 0 rgba(0,0,0,0.08); 12 | } 13 | 14 | /* Hide the images by default */ 15 | .mySlides { 16 | display: none; 17 | margin-bottom: 0; 18 | padding-bottom: 0; 19 | } 20 | 21 | /* Next & previous buttons */ 22 | .prev, .next { 23 | cursor: pointer; 24 | position: absolute; 25 | z-index: 100; 26 | top: 50%; 27 | width: auto; 28 | margin-top: -22px; 29 | padding: 20px; 30 | color: rgba(87, 87, 87, 0.47); 31 | font-weight: bold; 32 | font-size: 24px; 33 | transition: 0.6s ease; 34 | border-radius: 0 3px 3px 0; 35 | user-select: none; 36 | } 37 | 38 | .prev { 39 | float: left; 40 | left: 0; 41 | } 42 | 43 | .next { 44 | right: 0; 45 | float: right; 46 | } 47 | 48 | /* Position the "next button" to the right */ 49 | .next { 50 | right: 0; 51 | border-radius: 3px 0 0 3px; 52 | } 53 | 54 | /* On hover, add a black background color with a little bit see-through */ 55 | .prev:hover, .next:hover { 56 | background-color: rgba(0,0,0,0.8); 57 | } 58 | 59 | .sliderDot { 60 | display: inline; 61 | margin: 10px; 62 | } 63 | 64 | /* Caption text */ 65 | .text { 66 | color: #f2f2f2; 67 | font-size: 20px; 68 | padding: 8px 12px; 69 | position: absolute; 70 | bottom: 8px; 71 | width: 100%; 72 | text-align: center; 73 | } 74 | 75 | /* Number text (1/3 etc) */ 76 | .numbertext { 77 | color: #f2f2f2; 78 | font-size: .7em; 79 | padding: 8px 12px; 80 | position: absolute; 81 | top: 0; 82 | } 83 | 84 | /* The dots/bullets/indicators */ 85 | .dot { 86 | cursor: pointer; 87 | height: 12px; 88 | width: 12px; 89 | margin: 0 2px; 90 | background-color: #bbb; 91 | border-radius: 50%; 92 | display: inline-block; 93 | transition: background-color 0.6s ease; 94 | } 95 | 96 | .active, .dot:hover { 97 | background-color: #717171; 98 | } 99 | 100 | /* Fading animation */ 101 | .fade { 102 | -webkit-animation-name: fade; 103 | -webkit-animation-duration: 1.5s; 104 | animation-name: fade; 105 | animation-duration: 1.5s; 106 | } 107 | 108 | @-webkit-keyframes fade { 109 | from {opacity: .4} 110 | to {opacity: 1} 111 | } 112 | 113 | @keyframes fade { 114 | from {opacity: .4} 115 | to {opacity: 1} 116 | } -------------------------------------------------------------------------------- /frame-website/iconfonts/flaticon.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Flaticon"; 3 | src: url("flaticon.eot"); 4 | src: url("flaticon.eot#iefix") format("embedded-opentype"), 5 | url("flaticon.woff") format("woff"), 6 | url("flaticon.ttf") format("truetype"), 7 | url("flaticon.svg") format("svg"); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | [class^="flaticon-"]:before, [class*=" flaticon-"]:before, 12 | [class^="flaticon-"]:after, [class*=" flaticon-"]:after { 13 | font-family: Flaticon; 14 | 15 | font-style: normal; 16 | 17 | }.flaticon-aim:before { 18 | content: "\e000"; 19 | } 20 | .flaticon-arrow:before { 21 | content: "\e001"; 22 | } 23 | .flaticon-attachment:before { 24 | content: "\e002"; 25 | } 26 | .flaticon-battery:before { 27 | content: "\e003"; 28 | } 29 | .flaticon-bluetooth:before { 30 | content: "\e004"; 31 | } 32 | .flaticon-calendar:before { 33 | content: "\e005"; 34 | } 35 | .flaticon-call:before { 36 | content: "\e006"; 37 | } 38 | .flaticon-camera:before { 39 | content: "\e007"; 40 | } 41 | .flaticon-code:before { 42 | content: "\e008"; 43 | } 44 | .flaticon-connecting:before { 45 | content: "\e009"; 46 | } 47 | .flaticon-tick:before { 48 | content: "\e00a"; 49 | } 50 | .flaticon-facebook:before { 51 | content: "\e00b"; 52 | } 53 | .flaticon-google:before { 54 | content: "\e00c"; 55 | } 56 | .flaticon-graduates:before { 57 | content: "\e00d"; 58 | } 59 | .flaticon-heart:before { 60 | content: "\e00e"; 61 | } 62 | .flaticon-home:before { 63 | content: "\e00f"; 64 | } 65 | .flaticon-layers:before { 66 | content: "\e010"; 67 | } 68 | .flaticon-list:before { 69 | content: "\e011"; 70 | } 71 | .flaticon-mail:before { 72 | content: "\e012"; 73 | } 74 | .flaticon-more:before { 75 | content: "\e013"; 76 | } 77 | .flaticon-move:before { 78 | content: "\e014"; 79 | } 80 | .flaticon-outcoming:before { 81 | content: "\e015"; 82 | } 83 | .flaticon-pinterest:before { 84 | content: "\e016"; 85 | } 86 | .flaticon-play:before { 87 | content: "\e017"; 88 | } 89 | .flaticon-plus:before { 90 | content: "\e018"; 91 | } 92 | .flaticon-position:before { 93 | content: "\e019"; 94 | } 95 | .flaticon-round:before { 96 | content: "\e01a"; 97 | } 98 | .flaticon-settings:before { 99 | content: "\e01b"; 100 | } 101 | .flaticon-shopping:before { 102 | content: "\e01c"; 103 | } 104 | .flaticon-shutdown:before { 105 | content: "\e01d"; 106 | } 107 | .flaticon-special:before { 108 | content: "\e01e"; 109 | } 110 | .flaticon-speech:before { 111 | content: "\e01f"; 112 | } 113 | .flaticon-star:before { 114 | content: "\e020"; 115 | } 116 | .flaticon-twitter:before { 117 | content: "\e021"; 118 | } 119 | -------------------------------------------------------------------------------- /frame-website/iconfonts/flaticon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/iconfonts/flaticon.eot -------------------------------------------------------------------------------- /frame-website/iconfonts/flaticon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/iconfonts/flaticon.ttf -------------------------------------------------------------------------------- /frame-website/iconfonts/flaticon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/iconfonts/flaticon.woff -------------------------------------------------------------------------------- /frame-website/images/Frame-animated-demo-01-14-2019.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/Frame-animated-demo-01-14-2019.gif -------------------------------------------------------------------------------- /frame-website/images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/banner.png -------------------------------------------------------------------------------- /frame-website/images/frame_screenshot_01-21-2019_alice_in_wonderland_information_extraction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/frame_screenshot_01-21-2019_alice_in_wonderland_information_extraction.png -------------------------------------------------------------------------------- /frame-website/images/frame_screenshot_01-21-2019_cryptocurrency_analysis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/frame_screenshot_01-21-2019_cryptocurrency_analysis.png -------------------------------------------------------------------------------- /frame-website/images/frame_screenshot_01-21-2019_sicko_mode_visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/frame_screenshot_01-21-2019_sicko_mode_visualization.png -------------------------------------------------------------------------------- /frame-website/images/frame_screenshot_01-21-2019_this_is_water_summarization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/frame_screenshot_01-21-2019_this_is_water_summarization.png -------------------------------------------------------------------------------- /frame-website/images/framed_video_animation_demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/framed_video_animation_demo.mp4 -------------------------------------------------------------------------------- /frame-website/images/liveforms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/liveforms.png -------------------------------------------------------------------------------- /frame-website/images/scripteden-logo-g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/scripteden-logo-g.png -------------------------------------------------------------------------------- /frame-website/images/totoro-horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame-website/images/totoro-horizontal.jpg -------------------------------------------------------------------------------- /frame-website/js/homepage.js: -------------------------------------------------------------------------------- 1 | $(document) 2 | .ready(function() { 3 | 4 | var 5 | changeSides = function() { 6 | $('.ui.shape') 7 | .eq(0) 8 | .shape('flip over') 9 | .end() 10 | .eq(1) 11 | .shape('flip over') 12 | .end() 13 | .eq(2) 14 | .shape('flip back') 15 | .end() 16 | .eq(3) 17 | .shape('flip back') 18 | .end() 19 | ; 20 | }, 21 | validationRules = { 22 | firstName: { 23 | identifier : 'email', 24 | rules: [ 25 | { 26 | type : 'empty', 27 | prompt : 'Please enter an e-mail' 28 | }, 29 | { 30 | type : 'email', 31 | prompt : 'Please enter a valid e-mail' 32 | } 33 | ] 34 | } 35 | } 36 | ; 37 | 38 | $('.ui.dropdown') 39 | .dropdown({ 40 | on: 'hover' 41 | }) 42 | ; 43 | 44 | $('.ui.form') 45 | .form(validationRules, { 46 | on: 'blur' 47 | }) 48 | ; 49 | 50 | $('.masthead .information') 51 | .transition('scale in', 1000) 52 | ; 53 | 54 | setInterval(changeSides, 3000); 55 | 56 | }) 57 | ; -------------------------------------------------------------------------------- /frame-website/js/slideshow.js: -------------------------------------------------------------------------------- 1 | var slideIndex = 1; 2 | showSlides(slideIndex); 3 | 4 | // Next/previous controls 5 | function plusSlides(n) { 6 | showSlides(slideIndex += n); 7 | } 8 | 9 | // Thumbnail image controls 10 | function currentSlide(n) { 11 | showSlides(slideIndex = n); 12 | } 13 | 14 | function showSlides(n) { 15 | var i; 16 | var slides = document.getElementsByClassName("mySlides"); 17 | var dots = document.getElementsByClassName("dot"); 18 | if (n > slides.length) {slideIndex = 1} 19 | if (n < 1) {slideIndex = slides.length} 20 | for (i = 0; i < slides.length; i++) { 21 | slides[i].style.display = "none"; 22 | } 23 | for (i = 0; i < dots.length; i++) { 24 | dots[i].className = dots[i].className.replace(" active", ""); 25 | } 26 | if (slideIndex > slides.length) {slideIndex = 1} 27 | slides[slideIndex-1].style.display = "block"; 28 | dots[slideIndex-1].className += " active"; 29 | setTimeout(showSlides, 40000); // Change image every 40 seconds 30 | } -------------------------------------------------------------------------------- /frame/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "stage-3", "react", 3 | [ 4 | "env", 5 | { 6 | "targets": { 7 | "browsers": ["last 2 versions"] 8 | }, 9 | "debug": true, 10 | "modules": "commonjs" 11 | } 12 | ] 13 | ], 14 | "plugins": ["add-module-exports"], 15 | "env": { 16 | "test": { 17 | "plugins": [ 18 | "@babel/plugin-transform-modules-commonjs" 19 | ] 20 | }, 21 | "production": { 22 | "presets": ["react-optimize"], 23 | "plugins": ["dev-expression"] 24 | }, 25 | "development": { 26 | "plugins": [ 27 | ["transform-class-properties", { "spec": true }], 28 | "transform-es2015-classes", 29 | ["flow-runtime", { "assert": false, "annotate": true }], 30 | ["transform-runtime",{"helpers": false,"polyfill": false,"regenerator": true,"moduleName": "babel-runtime" 31 | } 32 | ] 33 | ] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /frame/.eslintignore: -------------------------------------------------------------------------------- 1 | package.json 2 | 3 | 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | .eslintcache 28 | 29 | # Dependency directory 30 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 31 | node_modules 32 | app/node_modules 33 | 34 | # OSX 35 | .DS_Store 36 | 37 | # flow-typed 38 | flow-typed/npm/* 39 | !flow-typed/npm/module_vx.x.x.js 40 | 41 | # App packaged 42 | release 43 | app/main.prod.js 44 | app/main.prod.js.map 45 | app/renderer.prod.js 46 | app/renderer.prod.js.map 47 | app/style.css 48 | app/style.css.map 49 | dist 50 | dll 51 | main.js 52 | main.js.map 53 | 54 | .idea 55 | npm-debug.log.* 56 | __snapshots__ 57 | 58 | assets 59 | vendor -------------------------------------------------------------------------------- /frame/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "prettier", "prettier/react"], 3 | "env": { 4 | "browser": true, 5 | "jest": true 6 | }, 7 | "rules": { 8 | "linebreak-style": 0, 9 | "react/jsx-filename-extension": 0, 10 | "react/prefer-stateless-function": 0 11 | }, 12 | "parser": "babel-eslint", 13 | "parserOptions": { 14 | "allowImportExportEverywhere": true, 15 | "sourceType": "module" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frame/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [options] -------------------------------------------------------------------------------- /frame/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | *.tar.gz filter=lfs diff=lfs merge=lfs -text 4 | -------------------------------------------------------------------------------- /frame/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "chrome", 6 | "request": "launch", 7 | "name": "Launch Chrome against localhost", 8 | "url": "http://localhost:3001", 9 | "webRoot": "${workspaceFolder}" 10 | }, 11 | { 12 | "type": "chrome", 13 | "request": "attach", 14 | "name": "Attach to Chrome", 15 | "port": 9222, 16 | "webRoot": "${workspaceFolder}" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /frame/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Format a file on save. A formatter must be available, the file must not be auto-saved, and editor must not be shutting down. 3 | "editor.formatOnSave": false, 4 | // Enable/disable JavaScript validation. (For Flow) 5 | "javascript.validate.enable": false, 6 | // Enable/disable default JavaScript formatter (For Prettier) 7 | "javascript.format.enable": true, 8 | // Use 'prettier-eslint' instead of 'prettier'. Other settings will only be fallbacks in case they could not be inferred from eslint rules. 9 | "prettier.eslintIntegration": true, 10 | 11 | // Is flow enabled 12 | "flow.enabled": true, 13 | 14 | // File extensions to consider for flow processing. 15 | "flow.fileExtensions": [ 16 | ".js", 17 | ".mjs", 18 | ".jsx", 19 | ".flow", 20 | ".json" 21 | ], 22 | // Path to flow binary. On Windows use '\\' as directory separator 23 | "flow.pathToFlow": "flow", 24 | 25 | // Run Flow on all files, No need to put //@flow comment on top of files. 26 | "flow.runOnAllFiles": false, 27 | 28 | // If true will run flow on every edit, otherwise will run only when changes are saved 29 | "flow.runOnEdit": true, 30 | 31 | // If true will display flow status is the statusbar 32 | "flow.showStatus": true, 33 | 34 | // Stop Flow on Exit 35 | "flow.stopFlowOnExit": true, 36 | 37 | // Support using flow through your node_modules folder, WARNING: Checking this box is a security risk. When you open a project we will immediately run code contained within it. 38 | "flow.useNPMPackagedFlow": true 39 | } -------------------------------------------------------------------------------- /frame/README.md: -------------------------------------------------------------------------------- 1 | # Frame - Electron & Web App 2 | 3 | Frontend components and config for Frame, which builds for both Electron and the web. 4 | 5 | IMPORT: Included in the folder is /custom_node_modules. You should replace the packages from this folder into your actual /node_modules after running "npm install", since there are certain unofficial fixes made to some libraries to fix bugs. 6 | 7 | Notes: 8 | 9 | - State management is done with key-value retrieval in Window.sessionStorage API and helper functions. As the project grows this should move to Redux and other libraries. 10 | - Currently only builds for Windows have been created. For Linux and Mac, this needs to be done on machines with those OSes. Linux could probably be built on a VM; this should be tried soon. 11 | 12 | # Installation 13 | To install all the packages run either: 14 | ```sh 15 | $ npm install 16 | ``` 17 | # Running the source for web 18 | To run in a browser using the webpack dev server in development mode with hot reloading: 19 | 20 | ```sh 21 | $ npm run start 22 | ``` 23 | 24 | # Running the source using Electron 25 | 26 | To run a development build with hot reloading in Electron: 27 | ```sh 28 | $ npm run electron-dev 29 | ``` 30 | 31 | # Building the source for the web 32 | 33 | To build for production: 34 | ```sh 35 | $ npm run build 36 | ``` 37 | To make a development build: 38 | ```sh 39 | $ npm run build-dev 40 | ``` 41 | 42 | # Building the source with Electron-Builder 43 | 44 | First build and minify the web files: 45 | ```sh 46 | $ npm run build 47 | ``` 48 | 49 | Then build binaries for distribution: 50 | 51 | Default platform (current machine): 52 | ```sh 53 | $ npm run electron-build 54 | ``` 55 | 56 | Or: 57 | 58 | ```sh 59 | $ npm run electron-build --linux 60 | ``` 61 | ```sh 62 | $ npm run electron-build --mac 63 | ``` 64 | ```sh 65 | $ npm run electron-build --windows 66 | ``` 67 | 68 | (The reason why the above build commands aren't combined in the package file is because this way it's easier to handle slashes in the paths across Windows and other platforms). 69 | 70 | Binary is saved along with its unpacked contents within ./dist. -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 0.6.0-beta 2 | 3 | - A revamped architecture develop custom editor in a better way using plugin-like system. 4 | - Updated draft-convert's version (@mckelvey) 5 | 6 | ### 0.5.5 7 | 8 | - A new prop `toolbarConfig` has been introduced. So instead of passing whole configuration into `blockButtons` and `inlineButtons`, you can just pass, `toolbarConfig` with value 9 | ```json 10 | {block: ["header-three", "blockquote", ...], inline: ["BOLD", "ITALIC", "UNDERLINE", "hyperlink"]} 11 | ``` 12 | Note that the string values of the array must already be present in `BLOCK_BUTTON` and `INLINE_BUTTONS` in `medium-draft` (@roy-gbiv) 13 | 14 | - Extra props can be passed to the `component` of each item in `sideButtons` inside the `prop` key. Earlier, only `title` and `component` were accepted. Now a 3rd key `prop` can also be passed whose keys can be accessed inside the `component` through `this.props` (@ jaspersorrio) 15 | - Fixed paste handling when cursor is inside image block caption. Earlier, the `src` of image became `undefined`. Now, plaintext will be pasted if the cursor is inside Image block. Otherwise, Draft's pasting will take over. 16 | - Now a string of text can also be passed to `createEditorState` as the first argument to create initial `editorState` pre-filled with the text. 17 | 18 | ### 0.5.3 19 | 20 | - Added `medium-draft-importer` to convert html exported using `medium-draft-exporter` to draft's json format (@Yukaii) 21 | - Fixed arrow navigation around image blocks 22 | - Allow inline styles to be applied to heading blocks 23 | - Remove hardcoded fonts from css files 24 | 25 | ### 0.5.2 26 | 27 | - Now, the toolbar buttons also accept a react component instead of just a string as label. 28 | This can be used to customize the icon of the toolbar button. For ex - in the 29 | demo, blockquote and link buttons are svg components which previously were 30 | just string labels. 31 | - Added a link info tooltip that shows up when cursor is inside a word with hyperlink. 32 | - The tooltip has option to edit that link or unlink. 33 | - Added medium's shortcut to add a link to text selection 34 | - CTRL/CMD + K -> Add link 35 | - CTRL/CMD + SHIFT + K -> Remove link if cursor is inside a word with link. 36 | 37 | ### 0.5.1 38 | 39 | - Optimized build process by minifying css and removing prop-types from the build files. 40 | - Migrated to React 15.5 (@baldwmic) with external `prop-types` dependency. 41 | 42 | ### 0.5.0 43 | 44 | - Moved away from the deprecated `Entity` usage of `draft-js` and updated to draft-js 0.10.1 (@valthon) 45 | - Fix for unintentional page navigation when adding links (@J00nz) 46 | - Fix where first click on side (+) button made it dissappear (@J00nz) 47 | - Accept only image files through file selector (@anthonyjgrove) 48 | 49 | ### 0.4.1 50 | 51 | - Added medium-draft-exporter to convert the draft-js JSON data to HTML. 52 | - Moved away from string refs to recommended refs in React. 53 | 54 | ### 0.4.0 55 | 56 | - Updated to use draft-js v0.9.1 57 | - Namespaced all classes to start with `md-` 58 | - Add relevant class to editor container based on whether editing is enabled or disabled 59 | -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Brijesh Bittu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/example/index.js: -------------------------------------------------------------------------------- 1 | // import React from 'react'; 2 | 3 | import 'draft-js/dist/Draft.css'; 4 | // eslint-disable-next-line 5 | import 'hint.css/hint.min.css'; 6 | 7 | import '../src/index.scss'; 8 | import '../src/components/addbutton.scss'; 9 | import '../src/components/toolbar.scss'; 10 | import '../src/components/blocks/text.scss'; 11 | import '../src/components/blocks/atomic.scss'; 12 | import '../src/components/blocks/blockquotecaption.scss'; 13 | import '../src/components/blocks/caption.scss'; 14 | import '../src/components/blocks/todo.scss'; 15 | import '../src/components/blocks/image.scss'; 16 | // import { Editor, createEditorState } from '../src/'; 17 | 18 | import { createEditor } from '../src/'; 19 | 20 | const handleQuoteInput = (str, { 21 | getEditorState, 22 | }) => { 23 | const editorState = getEditorState(); 24 | return editorState; 25 | }; 26 | 27 | const Editor = createEditor({ 28 | handleBeforeInput: handleQuoteInput, 29 | }); 30 | 31 | export default Editor; 32 | -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "medium-draft": "^0.6.0-beta" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Editor 6 | 7 | 8 | 49 | 50 | 51 |
Loading Editor
52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/basic.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * medium-draft 3 | * Version - 0.6.0-beta1 4 | * Author - Brijesh Bittu (http://bitwiser.in/) 5 | */ 6 | .md-block-header-one{font-size:2em}.md-block-header-two{font-size:1.7em}.md-block-header-three{font-size:1.3em}.md-block-header-four{font-size:1em}.md-block-header-five{font-size:.8em}.md-block-header-six{font-size:.7em}.md-block-header-five,.md-block-header-four,.md-block-header-one,.md-block-header-six,.md-block-header-three,.md-block-header-two{margin-bottom:5px}.md-block-blockquote{margin:0;padding-left:15px;border-left:5px solid #4ca8de;padding:10px 0 10px 20px;background-color:#e2f2ff;font-size:1.1em}.md-block-image{margin:0 0 10px}.md-block-image img{width:100%}.md-block-image figcaption{text-align:center;font-size:.9em}.md-block-todo{margin:10px 0}.md-block-todo input[type=checkbox]{float:left;position:relative;top:0;left:-2px}.md-block-todo p{margin-left:18px}.md-block-ordered-list-item,.md-block-unordered-list-item{padding-left:20px}.md-block-ordered-list-item li,.md-block-unordered-list-item li{margin-bottom:5px}.md-block-atomic-embed{margin:10px 0}.md-block-atomic-break hr{max-width:100px;border:2px solid #ccc}.md-inline-code{font-family:Consolas,Liberation Mono,Menlo,Courier,monospace;margin:4px 0;font-size:.9em;padding:1px 3px;color:#555;background-color:#fcfcfc;border-width:1px;border-style:solid;border-color:#ccc #ccc #bbb;border-image:initial;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.md-inline-link,.md-inline-link:visited{color:#08c}.md-inline-highlight{background:#ff0;display:inline;padding:2px 4px}p.md-block-block-quote-caption{margin-top:0;font-size:.8em;padding-top:5px;padding-bottom:5px;padding-left:10px;background:#fafafa}p.md-block-block-quote-caption:before{content:"\2013";color:#999;float:left;font-weight:700;display:inline;margin-right:10px} -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/blocks/atomic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _propTypes = require('prop-types'); 8 | 9 | var _propTypes2 = _interopRequireDefault(_propTypes); 10 | 11 | var _react = require('react'); 12 | 13 | var _react2 = _interopRequireDefault(_react); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | var AtomicBlock = function AtomicBlock(props) { 18 | var content = props && props.blockProps.getEditorState().getCurrentContent(); 19 | var entity = content.getEntity(props.block.getEntityAt(0)); 20 | var data = entity.getData(); 21 | var type = entity.getType(); 22 | if (type === 'image') { 23 | return _react2.default.createElement( 24 | 'div', 25 | { className: 'md-block-atomic-wrapper' }, 26 | _react2.default.createElement('img', { role: 'presentation', src: data.src }), 27 | _react2.default.createElement( 28 | 'div', 29 | { className: 'md-block-atomic-controls' }, 30 | _react2.default.createElement( 31 | 'button', 32 | null, 33 | '\xD7' 34 | ) 35 | ) 36 | ); 37 | } 38 | return _react2.default.createElement( 39 | 'p', 40 | null, 41 | 'No supported block for ', 42 | type 43 | ); 44 | }; 45 | // import './atomic.scss'; 46 | 47 | AtomicBlock.propTypes = { 48 | block: _propTypes2.default.object, 49 | getEditorState: _propTypes2.default.func 50 | }; 51 | 52 | exports.default = AtomicBlock; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/blocks/blockquotecaption.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require('react'); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | var _draftJs = require('draft-js'); 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | // import './blockquotecaption.scss'; 16 | 17 | exports.default = function (props) { 18 | return _react2.default.createElement( 19 | 'cite', 20 | null, 21 | _react2.default.createElement(_draftJs.EditorBlock, props) 22 | ); 23 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/blocks/break.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require("react"); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | exports.default = function () { 14 | return _react2.default.createElement("hr", { className: "md-block-hr" }); 15 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/blocks/caption.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require('react'); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | var _draftJs = require('draft-js'); 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | // import './caption.scss'; 16 | 17 | exports.default = function (props) { 18 | return _react2.default.createElement(_draftJs.EditorBlock, props); 19 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/blocks/text.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require('react'); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | var _draftJs = require('draft-js'); 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | // export default class Paragraph extends Component { 16 | // render(){ 17 | // return ( 18 | // 19 | // ); 20 | // } 21 | // } 22 | 23 | // import './text.scss'; 24 | 25 | exports.default = function (props) { 26 | return _react2.default.createElement(_draftJs.EditorBlock, props); 27 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/blocktoolbar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _propTypes = require('prop-types'); 10 | 11 | var _propTypes2 = _interopRequireDefault(_propTypes); 12 | 13 | var _react = require('react'); 14 | 15 | var _react2 = _interopRequireDefault(_react); 16 | 17 | var _draftJs = require('draft-js'); 18 | 19 | var _stylebutton = require('./stylebutton'); 20 | 21 | var _stylebutton2 = _interopRequireDefault(_stylebutton); 22 | 23 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 24 | 25 | var BlockToolbar = function BlockToolbar(props) { 26 | if (props.buttons.length < 1) { 27 | return null; 28 | } 29 | var editorState = props.editorState; 30 | 31 | var blockType = _draftJs.RichUtils.getCurrentBlockType(editorState); 32 | return _react2.default.createElement( 33 | 'div', 34 | { className: 'md-RichEditor-controls md-RichEditor-controls-block' }, 35 | props.buttons.map(function (type) { 36 | var iconLabel = {}; 37 | iconLabel.label = type.label; 38 | return _react2.default.createElement(_stylebutton2.default, _extends({}, iconLabel, { 39 | key: type.style, 40 | active: type.style === blockType, 41 | onToggle: props.onToggle, 42 | style: type.style, 43 | description: type.description 44 | })); 45 | }) 46 | ); 47 | }; 48 | 49 | BlockToolbar.propTypes = { 50 | buttons: _propTypes2.default.array, 51 | editorState: _propTypes2.default.object.isRequired, 52 | onToggle: _propTypes2.default.func 53 | }; 54 | 55 | exports.default = BlockToolbar; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/customrenderer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _blockquotecaption = require('./blocks/blockquotecaption'); 8 | 9 | var _blockquotecaption2 = _interopRequireDefault(_blockquotecaption); 10 | 11 | var _caption = require('./blocks/caption'); 12 | 13 | var _caption2 = _interopRequireDefault(_caption); 14 | 15 | var _atomic = require('./blocks/atomic'); 16 | 17 | var _atomic2 = _interopRequireDefault(_atomic); 18 | 19 | var _todo = require('./blocks/todo'); 20 | 21 | var _todo2 = _interopRequireDefault(_todo); 22 | 23 | var _image = require('./blocks/image'); 24 | 25 | var _image2 = _interopRequireDefault(_image); 26 | 27 | var _break = require('./blocks/break'); 28 | 29 | var _break2 = _interopRequireDefault(_break); 30 | 31 | var _constants = require('../util/constants'); 32 | 33 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 34 | 35 | exports.default = function (setEditorState, getEditorState) { 36 | return function (contentBlock) { 37 | // console.log(editorState, onChange); 38 | var type = contentBlock.getType(); 39 | switch (type) { 40 | case _constants.Block.BLOCKQUOTE_CAPTION: 41 | return { 42 | component: _blockquotecaption2.default 43 | }; 44 | case _constants.Block.CAPTION: 45 | return { 46 | component: _caption2.default 47 | }; 48 | case _constants.Block.ATOMIC: 49 | return { 50 | component: _atomic2.default, 51 | editable: false, 52 | props: { 53 | getEditorState: getEditorState 54 | } 55 | }; 56 | case _constants.Block.TODO: 57 | return { 58 | component: _todo2.default, 59 | props: { 60 | setEditorState: setEditorState, 61 | getEditorState: getEditorState 62 | } 63 | }; 64 | case _constants.Block.IMAGE: 65 | return { 66 | component: _image2.default, 67 | props: { 68 | setEditorState: setEditorState, 69 | getEditorState: getEditorState 70 | } 71 | }; 72 | case _constants.Block.BREAK: 73 | return { 74 | component: _break2.default, 75 | editable: false 76 | }; 77 | default: 78 | return null; 79 | } 80 | }; 81 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/entities/link.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.findLinkEntities = undefined; 7 | 8 | var _propTypes = require('prop-types'); 9 | 10 | var _propTypes2 = _interopRequireDefault(_propTypes); 11 | 12 | var _react = require('react'); 13 | 14 | var _react2 = _interopRequireDefault(_react); 15 | 16 | var _constants = require('../../util/constants'); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 19 | 20 | var findLinkEntities = exports.findLinkEntities = function findLinkEntities(contentBlock, callback, contentState) { 21 | contentBlock.findEntityRanges(function (character) { 22 | var entityKey = character.getEntity(); 23 | return entityKey !== null && contentState.getEntity(entityKey).getType() === _constants.Entity.LINK; 24 | }, callback); 25 | }; 26 | 27 | var Link = function Link(props) { 28 | var contentState = props.contentState, 29 | entityKey = props.entityKey; 30 | 31 | var _contentState$getEnti = contentState.getEntity(entityKey).getData(), 32 | url = _contentState$getEnti.url; 33 | 34 | return _react2.default.createElement( 35 | 'a', 36 | { 37 | className: 'md-link', 38 | href: url, 39 | rel: 'noopener noreferrer', 40 | target: '_blank', 41 | 'aria-label': url 42 | }, 43 | props.children 44 | ); 45 | }; 46 | 47 | Link.propTypes = { 48 | children: _propTypes2.default.node, 49 | entityKey: _propTypes2.default.string, 50 | contentState: _propTypes2.default.object.isRequired 51 | }; 52 | 53 | exports.default = Link; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/inlinetoolbar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _propTypes = require('prop-types'); 10 | 11 | var _propTypes2 = _interopRequireDefault(_propTypes); 12 | 13 | var _react = require('react'); 14 | 15 | var _react2 = _interopRequireDefault(_react); 16 | 17 | var _stylebutton = require('./stylebutton'); 18 | 19 | var _stylebutton2 = _interopRequireDefault(_stylebutton); 20 | 21 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 22 | 23 | var InlineToolbar = function InlineToolbar(props) { 24 | if (props.buttons.length < 1) { 25 | return null; 26 | } 27 | var currentStyle = props.editorState.getCurrentInlineStyle(); 28 | return _react2.default.createElement( 29 | 'div', 30 | { className: 'md-RichEditor-controls md-RichEditor-controls-inline' }, 31 | props.buttons.map(function (type) { 32 | var iconLabel = {}; 33 | iconLabel.label = type.label; 34 | return _react2.default.createElement(_stylebutton2.default, _extends({}, iconLabel, { 35 | key: type.style, 36 | active: currentStyle.has(type.style), 37 | onToggle: props.onToggle, 38 | style: type.style, 39 | description: type.description 40 | })); 41 | }) 42 | ); 43 | }; 44 | 45 | InlineToolbar.propTypes = { 46 | buttons: _propTypes2.default.array, 47 | editorState: _propTypes2.default.object.isRequired, 48 | onToggle: _propTypes2.default.func 49 | }; 50 | 51 | exports.default = InlineToolbar; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/sides/break.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | var _propTypes = require('prop-types'); 10 | 11 | var _propTypes2 = _interopRequireDefault(_propTypes); 12 | 13 | var _react = require('react'); 14 | 15 | var _react2 = _interopRequireDefault(_react); 16 | 17 | var _model = require('../../model'); 18 | 19 | var _constants = require('../../util/constants'); 20 | 21 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 22 | 23 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 24 | 25 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 26 | 27 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 28 | 29 | var BreakButton = function (_React$Component) { 30 | _inherits(BreakButton, _React$Component); 31 | 32 | function BreakButton(props) { 33 | _classCallCheck(this, BreakButton); 34 | 35 | var _this = _possibleConstructorReturn(this, (BreakButton.__proto__ || Object.getPrototypeOf(BreakButton)).call(this, props)); 36 | 37 | _this.onClick = _this.onClick.bind(_this); 38 | return _this; 39 | } 40 | 41 | _createClass(BreakButton, [{ 42 | key: 'onClick', 43 | value: function onClick() { 44 | this.props.setEditorState((0, _model.addNewBlock)(this.props.getEditorState(), _constants.Block.BREAK)); 45 | } 46 | }, { 47 | key: 'render', 48 | value: function render() { 49 | return _react2.default.createElement( 50 | 'button', 51 | { className: 'md-sb-button', onClick: this.onClick, type: 'button' }, 52 | _react2.default.createElement('i', { className: 'fa fa-minus' }) 53 | ); 54 | } 55 | }]); 56 | 57 | return BreakButton; 58 | }(_react2.default.Component); 59 | 60 | exports.default = BreakButton; 61 | 62 | 63 | BreakButton.propTypes = { 64 | setEditorState: _propTypes2.default.func, 65 | getEditorState: _propTypes2.default.func, 66 | close: _propTypes2.default.func 67 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/components/stylebutton.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | var _propTypes = require('prop-types'); 10 | 11 | var _propTypes2 = _interopRequireDefault(_propTypes); 12 | 13 | var _react = require('react'); 14 | 15 | var _react2 = _interopRequireDefault(_react); 16 | 17 | var _constants = require('../util/constants.js'); 18 | 19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 20 | 21 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 22 | 23 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 24 | 25 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 26 | 27 | var StyleButton = function (_React$Component) { 28 | _inherits(StyleButton, _React$Component); 29 | 30 | function StyleButton(props) { 31 | _classCallCheck(this, StyleButton); 32 | 33 | var _this = _possibleConstructorReturn(this, (StyleButton.__proto__ || Object.getPrototypeOf(StyleButton)).call(this, props)); 34 | 35 | _this.onToggle = function (e) { 36 | e.preventDefault(); 37 | _this.props.onToggle(_this.props.style); 38 | }; 39 | return _this; 40 | } 41 | 42 | _createClass(StyleButton, [{ 43 | key: 'render', 44 | value: function render() { 45 | if (this.props.style === _constants.HYPERLINK) { 46 | return null; 47 | } 48 | var className = 'md-RichEditor-styleButton'; 49 | if (this.props.active) { 50 | className += ' md-RichEditor-activeButton'; 51 | } 52 | className += ' md-RichEditor-styleButton-' + this.props.style.toLowerCase(); 53 | return _react2.default.createElement( 54 | 'span', 55 | { 56 | className: className + ' hint--top', 57 | onMouseDown: this.onToggle, 58 | 'aria-label': this.props.description 59 | }, 60 | this.props.icon ? _react2.default.createElement('i', { className: 'fa fa-' + this.props.icon }) : this.props.label 61 | ); 62 | } 63 | }]); 64 | 65 | return StyleButton; 66 | }(_react2.default.Component); 67 | 68 | exports.default = StyleButton; 69 | 70 | 71 | StyleButton.propTypes = { 72 | onToggle: _propTypes2.default.func, 73 | style: _propTypes2.default.string, 74 | active: _propTypes2.default.bool, 75 | icon: _propTypes2.default.string, 76 | label: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.element, _propTypes2.default.object]), 77 | description: _propTypes2.default.string 78 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/editor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createEditor = require('./createEditor'); 8 | 9 | var _createEditor2 = _interopRequireDefault(_createEditor); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | exports.default = (0, _createEditor2.default)(); -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/blockRenderMap.js: -------------------------------------------------------------------------------- 1 | "use strict"; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/blockRendererFn.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var customRendererFn = exports.customRendererFn = function customRendererFn(contentBlock, _ref) { 7 | var rendererFn = _ref.rendererFn, 8 | getEditorState = _ref.getEditorState, 9 | setEditorState = _ref.setEditorState; 10 | 11 | var customRenderer = rendererFn(setEditorState, getEditorState); 12 | return customRenderer(contentBlock); 13 | }; 14 | 15 | var handlerList = exports.handlerList = [customRendererFn]; 16 | 17 | var blockRendererFn = function blockRendererFn(contentBlock, options) { 18 | var handlers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : handlerList; 19 | var _iteratorNormalCompletion = true; 20 | var _didIteratorError = false; 21 | var _iteratorError = undefined; 22 | 23 | try { 24 | for (var _iterator = handlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 25 | var handler = _step.value; 26 | 27 | var res = handler(contentBlock, options); 28 | if (res) { 29 | return res; 30 | } 31 | } 32 | } catch (err) { 33 | _didIteratorError = true; 34 | _iteratorError = err; 35 | } finally { 36 | try { 37 | if (!_iteratorNormalCompletion && _iterator.return) { 38 | _iterator.return(); 39 | } 40 | } finally { 41 | if (_didIteratorError) { 42 | throw _iteratorError; 43 | } 44 | } 45 | } 46 | 47 | return null; 48 | }; 49 | 50 | exports.default = blockRendererFn; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/blockStyleFn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var inBuiltBlockStyleFn = exports.inBuiltBlockStyleFn = function inBuiltBlockStyleFn(block, _ref) { 7 | var bsFn = _ref.blockStyleFn; 8 | return bsFn(block); 9 | }; 10 | 11 | var handlerList = exports.handlerList = [inBuiltBlockStyleFn]; 12 | 13 | var blockStyleFn = function blockStyleFn(block, options) { 14 | var handlers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : handlerList; 15 | var _iteratorNormalCompletion = true; 16 | var _didIteratorError = false; 17 | var _iteratorError = undefined; 18 | 19 | try { 20 | for (var _iterator = handlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 21 | var handler = _step.value; 22 | 23 | var res = handler(block, options); 24 | if (res) { 25 | return res; 26 | } 27 | } 28 | } catch (err) { 29 | _didIteratorError = true; 30 | _iteratorError = err; 31 | } finally { 32 | try { 33 | if (!_iteratorNormalCompletion && _iterator.return) { 34 | _iterator.return(); 35 | } 36 | } finally { 37 | if (_didIteratorError) { 38 | throw _iteratorError; 39 | } 40 | } 41 | } 42 | 43 | return 'md-block'; 44 | }; 45 | 46 | exports.default = blockStyleFn; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/handleBeforeInput.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.handlerList = exports.handlerUsingBeforeInput = undefined; 7 | 8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** 9 | * This function is responsible for emitting various commands based on various key combos. 10 | */ 11 | 12 | var _constants = require('../util/constants'); 13 | 14 | var handlerUsingBeforeInput = exports.handlerUsingBeforeInput = function handlerUsingBeforeInput(str, _ref) { 15 | var getEditorState = _ref.getEditorState, 16 | beforeInput = _ref.beforeInput, 17 | stringToTypeMap = _ref.stringToTypeMap; 18 | 19 | var editorState = getEditorState(); 20 | var onChange = function onChange(es) { 21 | editorState = es; 22 | }; 23 | var behavior = beforeInput(editorState, str, onChange, stringToTypeMap); 24 | if (behavior === _constants.HANDLED) { 25 | return editorState; 26 | } 27 | return getEditorState(); 28 | }; 29 | 30 | var handlerList = exports.handlerList = [handlerUsingBeforeInput]; 31 | 32 | var handleBeforeInput = function handleBeforeInput(str, es, options) { 33 | var handlers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : handlerList; 34 | 35 | var originalEs = options.getEditorState(); 36 | var editorState = originalEs; 37 | 38 | var _getEs = function _getEs() { 39 | return editorState; 40 | }; 41 | var behavior = _constants.NOT_HANDLED; 42 | 43 | var _iteratorNormalCompletion = true; 44 | var _didIteratorError = false; 45 | var _iteratorError = undefined; 46 | 47 | try { 48 | for (var _iterator = handlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 49 | var handler = _step.value; 50 | 51 | editorState = handler(str, _extends({}, options, { 52 | getEditorState: _getEs 53 | })); 54 | if (editorState !== originalEs) { 55 | options.setEditorState(editorState); 56 | behavior = _constants.HANDLED; 57 | break; 58 | } 59 | } 60 | } catch (err) { 61 | _didIteratorError = true; 62 | _iteratorError = err; 63 | } finally { 64 | try { 65 | if (!_iteratorNormalCompletion && _iterator.return) { 66 | _iterator.return(); 67 | } 68 | } finally { 69 | if (_didIteratorError) { 70 | throw _iteratorError; 71 | } 72 | } 73 | } 74 | 75 | return behavior; 76 | }; 77 | 78 | exports.default = handleBeforeInput; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/handlePastedText.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.handlerList = exports.handlePasteInImageCaption = undefined; 7 | 8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 9 | 10 | var _draftJs = require('draft-js'); 11 | 12 | var _model = require('../model'); 13 | 14 | var _constants = require('../util/constants'); 15 | 16 | /** 17 | * If current block is image and text is pasted, add that as plain 18 | * text at the cursor position. 19 | */ 20 | var handlePasteInImageCaption = exports.handlePasteInImageCaption = function handlePasteInImageCaption(text, html, es, _ref) { 21 | var getEditorState = _ref.getEditorState; 22 | 23 | var editorState = getEditorState(); 24 | var currentBlock = (0, _model.getCurrentBlock)(editorState); 25 | if (currentBlock.getType() !== _constants.Block.IMAGE) { 26 | return editorState; 27 | } 28 | 29 | return _draftJs.EditorState.push(editorState, _draftJs.Modifier.insertText(editorState.getCurrentContent(), editorState.getSelection(), text)); 30 | }; 31 | 32 | var handlerList = exports.handlerList = [handlePasteInImageCaption]; 33 | 34 | var handlePastedText = function handlePastedText(text, html, es, options) { 35 | var handlers = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : handlerList; 36 | 37 | var originalEs = options.getEditorState(); 38 | var editorState = originalEs; 39 | 40 | var _getEs = function _getEs() { 41 | return editorState; 42 | }; 43 | var behavior = _constants.NOT_HANDLED; 44 | 45 | var _iteratorNormalCompletion = true; 46 | var _didIteratorError = false; 47 | var _iteratorError = undefined; 48 | 49 | try { 50 | for (var _iterator = handlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 51 | var handler = _step.value; 52 | 53 | editorState = handler(text, html, es, _extends({}, options, { 54 | getEditorState: _getEs 55 | })); 56 | if (editorState !== originalEs) { 57 | options.setEditorState(editorState); 58 | behavior = _constants.HANDLED; 59 | break; 60 | } 61 | } 62 | } catch (err) { 63 | _didIteratorError = true; 64 | _iteratorError = err; 65 | } finally { 66 | try { 67 | if (!_iteratorNormalCompletion && _iterator.return) { 68 | _iterator.return(); 69 | } 70 | } finally { 71 | if (_didIteratorError) { 72 | throw _iteratorError; 73 | } 74 | } 75 | } 76 | 77 | return behavior; 78 | }; 79 | 80 | exports.default = handlePastedText; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _onTab = require('./onTab'); 8 | 9 | var _onTab2 = _interopRequireDefault(_onTab); 10 | 11 | var _onUpArrow = require('./onUpArrow'); 12 | 13 | var _onUpArrow2 = _interopRequireDefault(_onUpArrow); 14 | 15 | var _handlePastedText = require('./handlePastedText'); 16 | 17 | var _handlePastedText2 = _interopRequireDefault(_handlePastedText); 18 | 19 | var _handleReturn = require('./handleReturn'); 20 | 21 | var _handleReturn2 = _interopRequireDefault(_handleReturn); 22 | 23 | var _handleKeyCommand = require('./handleKeyCommand'); 24 | 25 | var _handleKeyCommand2 = _interopRequireDefault(_handleKeyCommand); 26 | 27 | var _handleBeforeInput = require('./handleBeforeInput'); 28 | 29 | var _handleBeforeInput2 = _interopRequireDefault(_handleBeforeInput); 30 | 31 | var _blockRendererFn = require('./blockRendererFn'); 32 | 33 | var _blockRendererFn2 = _interopRequireDefault(_blockRendererFn); 34 | 35 | var _blockStyleFn = require('./blockStyleFn'); 36 | 37 | var _blockStyleFn2 = _interopRequireDefault(_blockStyleFn); 38 | 39 | var _keyBindingFn = require('./keyBindingFn'); 40 | 41 | var _keyBindingFn2 = _interopRequireDefault(_keyBindingFn); 42 | 43 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 44 | 45 | var defaultPlugins = { 46 | onTab: _onTab2.default, 47 | onUpArrow: _onUpArrow2.default, 48 | handlePastedText: _handlePastedText2.default, 49 | handleReturn: _handleReturn2.default, 50 | handleKeyCommand: _handleKeyCommand2.default, 51 | handleBeforeInput: _handleBeforeInput2.default, 52 | blockRendererFn: _blockRendererFn2.default, 53 | blockStyleFn: _blockStyleFn2.default, 54 | keyBindingFn: _keyBindingFn2.default 55 | }; 56 | 57 | exports.default = defaultPlugins; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/keyBindingFn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.handlerList = exports.customKeyBindingFn = undefined; 7 | 8 | var _draftJs = require('draft-js'); 9 | 10 | var customKeyBindingFn = exports.customKeyBindingFn = function customKeyBindingFn(e, _ref) { 11 | var kbFn = _ref.keyBindingFn; 12 | return kbFn(e); 13 | }; 14 | 15 | var handlerList = exports.handlerList = [customKeyBindingFn]; 16 | 17 | exports.default = function (e, options) { 18 | var handlers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : handlerList; 19 | var _iteratorNormalCompletion = true; 20 | var _didIteratorError = false; 21 | var _iteratorError = undefined; 22 | 23 | try { 24 | for (var _iterator = handlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 25 | var handler = _step.value; 26 | 27 | var res = handler(e, options); 28 | if (res) { 29 | return res; 30 | } 31 | } 32 | } catch (err) { 33 | _didIteratorError = true; 34 | _iteratorError = err; 35 | } finally { 36 | try { 37 | if (!_iteratorNormalCompletion && _iterator.return) { 38 | _iterator.return(); 39 | } 40 | } finally { 41 | if (_didIteratorError) { 42 | throw _iteratorError; 43 | } 44 | } 45 | } 46 | 47 | return (0, _draftJs.getDefaultKeyBinding)(e); 48 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/handlers/onTab.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.handlerList = exports.handleTabForListItems = undefined; 7 | 8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 9 | 10 | var _draftJs = require('draft-js'); 11 | 12 | var MAX_NESTING_LEVEL = 2; 13 | 14 | var handleTabForListItems = exports.handleTabForListItems = function handleTabForListItems(e, _ref) { 15 | var getEditorState = _ref.getEditorState; 16 | 17 | var editorState = getEditorState(); 18 | var newEditorState = _draftJs.RichUtils.onTab(e, editorState, MAX_NESTING_LEVEL); 19 | if (newEditorState === editorState) { 20 | return editorState; 21 | } 22 | return newEditorState; 23 | }; 24 | 25 | var handlerList = exports.handlerList = [handleTabForListItems]; 26 | 27 | var onTab = function onTab(e, options) { 28 | var handlers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : handlerList; 29 | var getEditorState = options.getEditorState, 30 | setEditorState = options.setEditorState; 31 | 32 | var newEditorState = handlers.reduce(function (editorState, handler) { 33 | return handler(e, _extends({}, options, { 34 | getEditorState: function getEditorState() { 35 | return editorState; 36 | } 37 | })); 38 | }, getEditorState()); 39 | setEditorState(newEditorState); 40 | }; 41 | 42 | exports.default = onTab; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/model/content.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _draftJs = require('draft-js'); 8 | 9 | var _link = require('../components/entities/link'); 10 | 11 | var _link2 = _interopRequireDefault(_link); 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | var defaultDecorators = new _draftJs.CompositeDecorator([{ 16 | strategy: _link.findLinkEntities, 17 | component: _link2.default 18 | }]); 19 | 20 | var createEditorState = function createEditorState() { 21 | var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; 22 | var decorators = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultDecorators; 23 | 24 | if (content === null) { 25 | return _draftJs.EditorState.createEmpty(decorators); 26 | } 27 | var contentState = null; 28 | if (typeof content === 'string') { 29 | contentState = _draftJs.ContentState.createFromText(content); 30 | } else { 31 | contentState = (0, _draftJs.convertFromRaw)(content); 32 | } 33 | return _draftJs.EditorState.createWithContent(contentState, decorators); 34 | }; 35 | 36 | exports.default = createEditorState; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/beforeinput.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.StringToTypeMap = undefined; 7 | 8 | var _model = require('../model'); 9 | 10 | var _constants = require('./constants'); 11 | 12 | /* 13 | This is a key value pair where the key is the string that is input while typing. 14 | While typing in an empty block, if the entered text matches any of the keys in 15 | this dictionary, that particular block's type will be changed to the value 16 | associated with that key. 17 | */ 18 | var StringToTypeMap = exports.StringToTypeMap = { 19 | '--': _constants.Block.BLOCKQUOTE + ':' + _constants.Block.BLOCKQUOTE_CAPTION + ':' + _constants.Block.CAPTION, 20 | '> ': _constants.Block.BLOCKQUOTE, 21 | '*.': _constants.Block.UL, 22 | '* ': _constants.Block.UL, 23 | '- ': _constants.Block.UL, 24 | '1.': _constants.Block.OL, 25 | '# ': _constants.Block.H1, 26 | '##': _constants.Block.H2, 27 | '==': _constants.Block.UNSTYLED, 28 | '[]': _constants.Block.TODO 29 | }; 30 | 31 | /* 32 | This function is called before text is input in a block in `draft-js`. It checks 33 | whether the input string (first 2 cahracters only) is present in the `StringToTypeMap` 34 | mapping or not. If present, it converts the current block's type and called the `editor`'s 35 | `onChange` function. Otherwise, does nothing. By defualt, the above key-value mapping 36 | is passed. In custom implementation, users can pass their own mapping or extend 37 | the current one. 38 | */ 39 | var beforeInput = function beforeInput(editorState, inputString, onChange) { 40 | var mapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : StringToTypeMap; 41 | 42 | var selection = editorState.getSelection(); 43 | var block = (0, _model.getCurrentBlock)(editorState); 44 | var blockType = block.getType(); 45 | if (blockType.indexOf(_constants.Block.ATOMIC) === 0) { 46 | return _constants.NOT_HANDLED; 47 | } 48 | var blockLength = block.getLength(); 49 | if (selection.getAnchorOffset() > 1 || blockLength > 1) { 50 | return _constants.NOT_HANDLED; 51 | } 52 | var blockTo = mapping[block.getText()[0] + inputString]; 53 | if (!blockTo) { 54 | return _constants.NOT_HANDLED; 55 | } 56 | var finalType = blockTo.split(':'); 57 | if (finalType.length < 1 || finalType.length > 3) { 58 | return _constants.NOT_HANDLED; 59 | } 60 | var fType = finalType[0]; 61 | if (finalType.length === 1) { 62 | if (blockType === finalType[0]) { 63 | return _constants.NOT_HANDLED; 64 | } 65 | } else if (finalType.length === 2) { 66 | if (blockType === finalType[1]) { 67 | return _constants.NOT_HANDLED; 68 | } 69 | if (blockType === finalType[0]) { 70 | fType = finalType[1]; 71 | } 72 | } else if (finalType.length === 3) { 73 | if (blockType === finalType[2]) { 74 | return _constants.NOT_HANDLED; 75 | } 76 | if (blockType === finalType[0]) { 77 | fType = finalType[1]; 78 | } else { 79 | fType = finalType[2]; 80 | } 81 | } 82 | onChange((0, _model.resetBlockWithType)(editorState, fType, { 83 | text: '' 84 | })); 85 | return _constants.HANDLED; 86 | }; 87 | 88 | exports.default = beforeInput; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/blockStyleFn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _constants = require('./constants'); 8 | 9 | /* 10 | Get custom classnames for each of the different block types supported. 11 | */ 12 | 13 | var BASE_BLOCK_CLASS = 'md-block'; 14 | 15 | exports.default = function (block) { 16 | switch (block.getType()) { 17 | case _constants.Block.BLOCKQUOTE: 18 | return BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-quote md-RichEditor-blockquote'; 19 | case _constants.Block.UNSTYLED: 20 | return BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-paragraph'; 21 | case _constants.Block.ATOMIC: 22 | return BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-atomic'; 23 | case _constants.Block.CAPTION: 24 | return BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-caption'; 25 | case _constants.Block.TODO: 26 | { 27 | var data = block.getData(); 28 | var checkedClass = data.get('checked') === true ? BASE_BLOCK_CLASS + '-todo-checked' : BASE_BLOCK_CLASS + '-todo-unchecked'; 29 | var finalClass = BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-paragraph '; 30 | finalClass += BASE_BLOCK_CLASS + '-todo ' + checkedClass; 31 | return finalClass; 32 | } 33 | case _constants.Block.IMAGE: 34 | return BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-image'; 35 | case _constants.Block.BLOCKQUOTE_CAPTION: 36 | { 37 | var cls = BASE_BLOCK_CLASS + ' ' + BASE_BLOCK_CLASS + '-quote'; 38 | return cls + ' md-RichEditor-blockquote ' + BASE_BLOCK_CLASS + '-quote-caption'; 39 | } 40 | default: 41 | return BASE_BLOCK_CLASS; 42 | } 43 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/constants.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | /* 7 | Some of the constants which are used throughout this project instead of 8 | directly using string. 9 | */ 10 | 11 | var Block = exports.Block = { 12 | UNSTYLED: 'unstyled', 13 | PARAGRAPH: 'unstyled', 14 | OL: 'ordered-list-item', 15 | UL: 'unordered-list-item', 16 | H1: 'header-one', 17 | H2: 'header-two', 18 | H3: 'header-three', 19 | H4: 'header-four', 20 | H5: 'header-five', 21 | H6: 'header-six', 22 | CODE: 'code-block', 23 | BLOCKQUOTE: 'blockquote', 24 | PULLQUOTE: 'pullquote', 25 | ATOMIC: 'atomic', 26 | BLOCKQUOTE_CAPTION: 'block-quote-caption', 27 | CAPTION: 'caption', 28 | TODO: 'todo', 29 | IMAGE: 'atomic:image', 30 | BREAK: 'atomic:break' 31 | }; 32 | 33 | var Inline = exports.Inline = { 34 | BOLD: 'BOLD', 35 | CODE: 'CODE', 36 | ITALIC: 'ITALIC', 37 | STRIKETHROUGH: 'STRIKETHROUGH', 38 | UNDERLINE: 'UNDERLINE', 39 | HIGHLIGHT: 'HIGHLIGHT' 40 | }; 41 | 42 | var Entity = exports.Entity = { 43 | LINK: 'LINK' 44 | }; 45 | 46 | var HYPERLINK = exports.HYPERLINK = 'hyperlink'; 47 | var HANDLED = exports.HANDLED = 'handled'; 48 | var NOT_HANDLED = exports.NOT_HANDLED = 'not_handled'; 49 | 50 | var KEY_COMMANDS = exports.KEY_COMMANDS = { 51 | addNewBlock: function addNewBlock() { 52 | return 'add-new-block'; 53 | }, 54 | changeType: function changeType() { 55 | var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 56 | return 'changetype:' + type; 57 | }, 58 | showLinkInput: function showLinkInput() { 59 | return 'showlinkinput'; 60 | }, 61 | unlink: function unlink() { 62 | return 'unlink'; 63 | }, 64 | toggleInline: function toggleInline() { 65 | var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 66 | return 'toggleinline:' + type; 67 | }, 68 | deleteBlock: function deleteBlock() { 69 | return 'delete-block'; 70 | } 71 | }; 72 | 73 | exports.default = { 74 | Block: Block, 75 | Inline: Inline, 76 | Entity: Entity 77 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/customstylemap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _customStyleMap; 8 | 9 | var _constants = require('./constants'); 10 | 11 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 12 | 13 | /* 14 | Custom style map for custom entities like Hihglight. 15 | */ 16 | var customStyleMap = (_customStyleMap = {}, _defineProperty(_customStyleMap, _constants.Inline.HIGHLIGHT, { 17 | backgroundColor: 'yellow' 18 | }), _defineProperty(_customStyleMap, _constants.Inline.CODE, { 19 | fontFamily: 'Consolas, "Liberation Mono", Menlo, Courier, monospace', 20 | margin: '4px 0', 21 | fontSize: '0.9em', 22 | padding: '1px 3px', 23 | color: '#555', 24 | backgroundColor: '#fcfcfc', 25 | border: '1px solid #ccc', 26 | borderBottomColor: '#bbb', 27 | borderRadius: 3, 28 | boxShadow: 'inset 0 -1px 0 #bbb' 29 | }), _customStyleMap); 30 | 31 | exports.default = customStyleMap; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | /* 7 | Returns the `boundingClientRect` of the passed selection. 8 | */ 9 | var getSelectionRect = exports.getSelectionRect = function getSelectionRect(selected) { 10 | var _rect = selected.getRangeAt(0).getBoundingClientRect(); 11 | // selected.getRangeAt(0).getBoundingClientRect() 12 | var rect = _rect && _rect.top ? _rect : selected.getRangeAt(0).getClientRects()[0]; 13 | if (!rect) { 14 | if (selected.anchorNode && selected.anchorNode.getBoundingClientRect) { 15 | rect = selected.anchorNode.getBoundingClientRect(); 16 | rect.isEmptyline = true; 17 | } else { 18 | return null; 19 | } 20 | } 21 | return rect; 22 | }; 23 | 24 | /* 25 | Returns the native selection node. 26 | */ 27 | var getSelection = exports.getSelection = function getSelection(root) { 28 | var t = null; 29 | if (root.getSelection) { 30 | t = root.getSelection(); 31 | } else if (root.document.getSelection) { 32 | t = root.document.getSelection(); 33 | } else if (root.document.selection) { 34 | t = root.document.selection.createRange().text; 35 | } 36 | return t; 37 | }; 38 | 39 | /* 40 | Recursively finds the DOM Element of the block where the cursor is currently present. 41 | If not found, returns null. 42 | */ 43 | var getSelectedBlockNode = exports.getSelectedBlockNode = function getSelectedBlockNode(root) { 44 | var selection = root.getSelection(); 45 | if (selection.rangeCount === 0) { 46 | return null; 47 | } 48 | var node = selection.getRangeAt(0).startContainer; 49 | // console.log(node); 50 | do { 51 | if (node.getAttribute && node.getAttribute('data-block') === 'true') { 52 | return node; 53 | } 54 | node = node.parentNode; 55 | // console.log(node); 56 | } while (node !== null); 57 | return null; 58 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/keybinding.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _draftJs = require('draft-js'); 8 | 9 | var _constants = require('./constants'); 10 | 11 | var changeType = _constants.KEY_COMMANDS.changeType, 12 | showLinkInput = _constants.KEY_COMMANDS.showLinkInput, 13 | unlink = _constants.KEY_COMMANDS.unlink; 14 | 15 | /* 16 | Emits various key commands to be used by `handleKeyCommand` in `Editor` based 17 | on various key combos. 18 | */ 19 | 20 | exports.default = function (e) { 21 | if (_draftJs.KeyBindingUtil.hasCommandModifier(e) && e.which === 75) { 22 | if (e.shiftKey) { 23 | return unlink(); 24 | } 25 | return showLinkInput(); 26 | } 27 | if (e.altKey === true && !e.ctrlKey) { 28 | if (e.shiftKey === true) { 29 | switch (e.which) { 30 | // Alt + Shift + A 31 | // case 65: return addNewBlock(); 32 | default: 33 | return (0, _draftJs.getDefaultKeyBinding)(e); 34 | } 35 | } 36 | switch (e.which) { 37 | // 1 38 | case 49: 39 | return changeType('ordered-list-item'); 40 | // @ 41 | case 50: 42 | return showLinkInput(); 43 | // # 44 | case 51: 45 | return changeType('header-three'); 46 | // * 47 | case 56: 48 | return changeType('unordered-list-item'); 49 | // < 50 | case 188: 51 | return changeType('caption'); 52 | // // - 53 | // case 189: return 'changetype:caption'; 54 | // > 55 | case 190: 56 | return changeType('unstyled'); 57 | // " 58 | case 222: 59 | return changeType('blockquote'); 60 | default: 61 | return (0, _draftJs.getDefaultKeyBinding)(e); 62 | } 63 | } 64 | // if (e.keyCode === 46 && !e.ctrlKey) { 65 | // return KEY_COMMANDS.deleteBlock(); 66 | // } 67 | return (0, _draftJs.getDefaultKeyBinding)(e); 68 | }; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/lib/util/rendermap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _Map; 8 | 9 | var _immutable = require('immutable'); 10 | 11 | var _draftJs = require('draft-js'); 12 | 13 | var _constants = require('./constants'); 14 | 15 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 16 | 17 | /* 18 | Mapping that returns containers for the various block types. 19 | */ 20 | var RenderMap = (0, _immutable.Map)((_Map = {}, _defineProperty(_Map, _constants.Block.CAPTION, { 21 | element: 'cite' 22 | }), _defineProperty(_Map, _constants.Block.BLOCKQUOTE_CAPTION, { 23 | element: 'blockquote' 24 | }), _defineProperty(_Map, _constants.Block.TODO, { 25 | element: 'div' 26 | }), _defineProperty(_Map, _constants.Block.IMAGE, { 27 | element: 'figure' 28 | }), _defineProperty(_Map, _constants.Block.BREAK, { 29 | element: 'div' 30 | }), _Map)).merge(_draftJs.DefaultDraftBlockRenderMap); 31 | 32 | exports.default = RenderMap; -------------------------------------------------------------------------------- /frame/custom_node_modules/medium-draft/rendered.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Rendered Content | medium-draft 6 | 7 | 20 | 21 | 22 |
23 |

24 | Open this page by clicking the Render HTML button. 25 |

26 |
27 | 28 | 29 | 30 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /frame/custom_node_modules/node-sumbasic/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Vincent Utomo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /frame/custom_node_modules/node-sumbasic/README.md: -------------------------------------------------------------------------------- 1 | # node-sumbasic 2 | Implementation of SumBasic on NodeJS. 3 | 4 | Sumbasic is a popular baseline method for document summarization. The explanation could be read from the original paper: Nenkova, A. and Vanderwende, L., 2005. The impact of frequency on summarization. Microsoft Research, Redmond, Washington, Tech. Rep. MSR-TR-2005, 101. 5 | 6 | Here, the SumBasic are created as module inside `./src/index.js`. 7 | 8 | ### NPM package ### 9 | - Run `npm install node-sumbasic --save` 10 | - Require it in your project `const sumBasic = require('node-sumbasic')` 11 | - Call it `sumBasic(documents, target_summary_length, minimum_sentence_length_considered [optional])` 12 | - Example `sumBasic(documents, 100)` 13 | 14 | ### Demo run in project folder ### 15 | - Make sure to install the npm modules first `npm install` 16 | - In the project, run `node ./src/demo.js` 17 | 18 | ### What's new ### 19 | 20 | 0.1.7 21 | - Change dependencies from natural to stemmer 22 | - Add minimum sentence length to the optional parameter 23 | 24 | 25 | -------------------------------------------------------------------------------- /frame/custom_node_modules/node-sumbasic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "node-sumbasic", 3 | "_id": "node-sumbasic@0.1.7", 4 | "_inBundle": false, 5 | "_integrity": "sha512-xHMmNpIz55Ptj7rOTj2vSBBt6vPLfENsRuNVKhhPpOcm+2+77/GLGkEpSIVJ4Qd2m0WhQdZlyHnMOPM1ATxTYg==", 6 | "_location": "/node-sumbasic", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "node-sumbasic", 12 | "name": "node-sumbasic", 13 | "escapedName": "node-sumbasic", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/node-sumbasic/-/node-sumbasic-0.1.7.tgz", 23 | "_shasum": "379a068cda43c49b33b55c930dc0ff00dfc84e86", 24 | "_spec": "node-sumbasic", 25 | "_where": "C:\\Users\\JD\\Documents\\Git\\frame\\frame", 26 | "author": { 27 | "name": "MSVCode", 28 | "email": "msvcode@gmail.com" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/MSVCode/node-sumbasic/issues" 32 | }, 33 | "bundleDependencies": false, 34 | "dependencies": { 35 | "stemmer": "^1.0.2" 36 | }, 37 | "deprecated": false, 38 | "description": "NodeJS implementation of popular baseline document summarizer 'SumBasic'.", 39 | "homepage": "https://github.com/MSVCode/node-sumbasic", 40 | "keywords": [ 41 | "summarizer", 42 | "sumbasic", 43 | "summarization", 44 | "document" 45 | ], 46 | "license": "MIT", 47 | "main": ".\\src\\index.js", 48 | "name": "node-sumbasic", 49 | "repository": { 50 | "type": "git", 51 | "url": "git+https://github.com/MSVCode/node-sumbasic.git" 52 | }, 53 | "version": "0.1.7" 54 | } 55 | -------------------------------------------------------------------------------- /frame/custom_node_modules/node-sumbasic/src/demo.js: -------------------------------------------------------------------------------- 1 | var titles = [ 2 | "Google is urging more manufacturers to enable a new security feature in Android Oreo that detects if a device has been downgraded to an earlier version of the OS. Known as rollback protection, the measure adds another layer of security in the event a device is lost or stolen, and the attacker rolls it back to an older Android firmware with known vulnerabilities. Google revealed some details about rollback protection in September, which caught the attention of Android enthusiasts who like the freedom to downgrade Android as they see fit, even though it could be a security risk. While the security feature is part of Oreo, it's not available on every Android device that runs Oreo. According to Google, rollback protection works in tandem with Project Treble, the major redesign of Android in Oreo that separates the Android platform from vendor code. The modular design aims to help Android OEMs deliver new versions of Android to end-users faster. However, Project Treble is only supported on new devices that ship with Android, rather than devices that get upgraded to Oreo. So new handsets like the Pixel 2 and Sony Xperia XZ1 are Treble-compatible, while the Nokia 8 isn't.", 3 | 'Security has long been a sore point for enterprise Android users, but Google has taken steps to improve security in the OS with Android Oreo. In a Wednesday blog post, the firm detailed a feature called rollback protection, which prevents a device from starting up if it has been downgraded to an older OS version that may contain security vulnerabilities. This means that if your business phone is stolen, it will be more difficult for a hacker to leverage security flaws found in a previous version of the OS and access your data. This could add piece of mind for IT professionals managing Android devices in the workplace. While rollback protection is part of Android Oreo, it is up to the individual manufacturers of Android devices to enable the feature, as noted by our sister site ZDNet. Rollback protection is part of Andriod Verified Boot 2.0 (AVB), designed to stop devices from starting up with software that has been altered by hackers, according to the blog post from security team member Gian G. Spicuzza. AVB runs with Project Treble, a "major re-architect" of the Android OS framework meant to make it easier for manufacturers to update to new versions of the OS.', 4 | "Since Android Oreo was made available to Pixel and Nexus devices, Google has been working to harden the security of the mobile platform. Today, the company announced some of the improvements they made in the security department throughout the last few months. Some of these security features have already been implemented like making it safer to get apps and dropping insecure network protocol, while others may be released in the not so distant future. Google confirmed that it's expanding support for hardware security, which means they have added a reference implementation for Verified Boot running with Project Treble. Verified Boot is a special security feature that's been designed to prevent devices from booting up with software that has been tampered with. The improved security implementation is called Android Verified Boot 2.0 (AVB) and offers some nifty features that should allow for easier updates and more security, including rollback protection. The latter will prevent a device to boot if downgraded to an older OS version that might be vulnerable to an exploit. Then, Android Oreo now features the new OEM Lock Hardware Abstraction Layer (HAL), which should offer device manufacturers more flexibility for how they protect in case a device is locked, unlocked, or unlockable. There are many other under the hood security improvements Google implemented into Android Oreo, so make sure to hit the source link for the full list." 5 | ]; 6 | 7 | var summary = require('./index'); 8 | console.log(summary(titles,50)); 9 | var i=0; -------------------------------------------------------------------------------- /frame/public/electron.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron'); 2 | const app = electron.app; 3 | const BrowserWindow = electron.BrowserWindow; 4 | 5 | const path = require('path'); 6 | const url = require('url'); 7 | const isDev = require('electron-is-dev'); 8 | 9 | let mainWindow; 10 | 11 | function createWindow() { 12 | mainWindow = new BrowserWindow({width: 1920, height: 1280}); 13 | mainWindow.loadURL(`file://${path.join(__dirname, '../output/webpack/production/index.html')}`); 14 | // mainWindow.webContents.openDevTools(); 15 | mainWindow.on('closed', () => mainWindow = null); 16 | } 17 | 18 | app.on('ready', createWindow); 19 | 20 | app.on('window-all-closed', () => { 21 | if (process.platform !== 'darwin') { 22 | app.quit(); 23 | } 24 | }); 25 | 26 | app.on('activate', () => { 27 | if (mainWindow === null) { 28 | createWindow(); 29 | } 30 | }); 31 | 32 | // mainWindow.once('ready-to-show', () => { 33 | // mainWindow.show(); 34 | // // Open the DevTools automatically if developing 35 | // mainWindow.webContents.openDevTools(); 36 | // }); 37 | 38 | -------------------------------------------------------------------------------- /frame/src/assets/css/brands.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.6.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face { 6 | font-family: 'Font Awesome 5 Brands'; 7 | font-style: normal; 8 | font-weight: normal; 9 | src: url("../webfonts/fa-brands-400.eot"); 10 | src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); } 11 | 12 | .fab { 13 | font-family: 'Font Awesome 5 Brands'; } 14 | -------------------------------------------------------------------------------- /frame/src/assets/css/brands.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.6.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"} -------------------------------------------------------------------------------- /frame/src/assets/css/regular.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.6.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face { 6 | font-family: 'Font Awesome 5 Free'; 7 | font-style: normal; 8 | font-weight: 400; 9 | src: url("../webfonts/fa-regular-400.eot"); 10 | src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); } 11 | 12 | .far { 13 | font-family: 'Font Awesome 5 Free'; 14 | font-weight: 400; } 15 | -------------------------------------------------------------------------------- /frame/src/assets/css/regular.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.6.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Free";font-weight:400} -------------------------------------------------------------------------------- /frame/src/assets/css/solid.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.6.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face { 6 | font-family: 'Font Awesome 5 Free'; 7 | font-style: normal; 8 | font-weight: 900; 9 | src: url("../webfonts/fa-solid-900.eot"); 10 | src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); } 11 | 12 | .fa, 13 | .fas { 14 | font-family: 'Font Awesome 5 Free'; 15 | font-weight: 900; } 16 | -------------------------------------------------------------------------------- /frame/src/assets/css/solid.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.6.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900} -------------------------------------------------------------------------------- /frame/src/assets/electron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/electron.png -------------------------------------------------------------------------------- /frame/src/assets/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/flow.png -------------------------------------------------------------------------------- /frame/src/assets/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/github.png -------------------------------------------------------------------------------- /frame/src/assets/redux.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /frame/src/assets/semantic-ui-react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/semantic-ui-react.png -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /frame/src/assets/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/assets/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /frame/src/assets/webpack.svg: -------------------------------------------------------------------------------- 1 | icon-square-small -------------------------------------------------------------------------------- /frame/src/components/Ask/Ask.scss: -------------------------------------------------------------------------------- 1 | .askWrapper { 2 | margin: 0px !important; 3 | padding: 0px !important; 4 | height: 100% !important; 5 | margin-left: auto !important; 6 | margin-right: auto !important; 7 | max-width: calc(65% - 20px) !important; 8 | padding-left: 100px !important; 9 | } 10 | 11 | .questionTextInput { 12 | z-index: 1000 !important; 13 | width: calc(60% - 20px) !important; 14 | height: 50px !important; 15 | margin-top: 18px !important; 16 | margin-left: auto !important; 17 | margin-right: auto !important; 18 | margin-left: 90px !important; 19 | } 20 | 21 | .passageTextDisabled { 22 | width: calc(55% - 20px) !important; 23 | height: 80px !important; 24 | display: none !important; 25 | margin-left: auto !important; 26 | margin-right: auto !important; 27 | } 28 | 29 | .floatingAskButton { 30 | width: calc(60% - 20px) !important; 31 | z-index: 1000 !important; 32 | text-align: center !important; 33 | margin-left: auto !important; 34 | margin-right: auto !important; 35 | margin-left: 90px !important; 36 | // position: sticky !important; 37 | // text-align: center !important; 38 | } 39 | 40 | .smallDetailText { 41 | width: calc(60% - 20px) !important; 42 | // margin-right: auto !important; 43 | // margin-left: auto !important; 44 | margin-left: auto !important; 45 | margin-right: auto !important; 46 | margin-left: 85px !important; 47 | text-align: center !important; 48 | font-size: 1.05vmax !important; 49 | margin-top: 8px !important; 50 | letter-spacing: 1px !important; 51 | // text-align: center !important; 52 | } 53 | 54 | .answerText { 55 | width: calc(60% - 20px) !important; 56 | // margin-right: auto !important; 57 | // margin-left: auto !important; 58 | // margin-left: 100px !important; 59 | margin-left: auto !important; 60 | margin-right: auto !important; 61 | text-align: center !important; 62 | font-size: 1.05vmax !important; 63 | margin-top: 8px !important; 64 | letter-spacing: 1px !important; 65 | color: rgba(204, 204, 204, .8) !important; 66 | // text-align: center !important; 67 | } 68 | -------------------------------------------------------------------------------- /frame/src/components/AskMain/AskMain.scss: -------------------------------------------------------------------------------- 1 | .askWrapperMain { 2 | margin: 0px !important; 3 | padding: 0px !important; 4 | height: 100% !important; 5 | } 6 | 7 | .questionTextInputMain { 8 | margin: 0px !important; 9 | padding: 0px !important; 10 | z-index: 1000 !important; 11 | height: 50px !important; 12 | margin-top: 18px !important; 13 | text-align: center !important; 14 | width: calc(70% - 20px) !important; 15 | margin-left: auto !important; 16 | margin-right: auto !important; 17 | } 18 | 19 | .passageTextDisabled { 20 | height: 80px !important; 21 | display: none !important; 22 | } 23 | 24 | .floatingAskButtonMain { 25 | margin: 0px !important; 26 | padding: 0px !important; 27 | z-index: 1000 !important; 28 | text-align: center !important; 29 | width: calc(70% - 20px) !important; 30 | margin-left: auto !important; 31 | margin-right: auto !important; 32 | // text-align: center !important; 33 | } 34 | 35 | .smallDetailTextAskMain { 36 | margin-right: auto !important; 37 | margin-left: auto !important; 38 | color: rgba(88, 88, 88, 1.0) !important; 39 | font-size: 1.05em !important; 40 | margin-top: 8px !important; 41 | letter-spacing: 1px !important; 42 | width: calc(70% - 20px) !important; 43 | margin-left: auto !important; 44 | margin-right: auto !important; 45 | text-align: center !important; 46 | // text-align: center !important; 47 | } 48 | 49 | 50 | .answerTextAskMain { 51 | margin-right: auto !important; 52 | margin-left: auto !important; 53 | width: calc(70% - 20px) !important; 54 | margin: 0px !important; 55 | padding: 0px !important; 56 | font-size: 1.25em !important; 57 | margin-top: 8px !important; 58 | margin-left: auto !important; 59 | margin-right: auto !important; 60 | letter-spacing: 1px !important; 61 | color: rgba(204, 204, 204, .8) !important; 62 | text-align: center !important; 63 | margin-bottom: 15px !important; 64 | // text-align: center !important; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /frame/src/components/Brand/Brand.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import React, { Component } from 'react'; 3 | import styles from './Brand.scss'; 4 | 5 | export default class Brand extends Component { 6 | componentDidMount() { 7 | const options = { onChange: this.props.onChange }; 8 | this._container = document.getElementById('jsonEditor'); 9 | } 10 | 11 | render() { 12 | return ( 13 |
14 |
15 |

F R A M E

v 0.1.0

16 |
17 |
18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frame/src/components/Brand/Brand.scss: -------------------------------------------------------------------------------- 1 | .brandContainer { 2 | width: 100%; 3 | height: 100%; 4 | margin-top: 1px; 5 | padding-right: 5px; 6 | padding-left: 5px; 7 | padding-top: 10px; 8 | padding-bottom: 10px; 9 | max-height: 53px; 10 | overflow: hidden; 11 | } 12 | 13 | .brandContainer:hover { 14 | // -moz-box-shadow: 0 0 4px rgb(208, 255, 0); 15 | // -webkit-box-shadow: 0 4 6px rgb(208, 255, 0); 16 | // box-shadow: 0px 0px 4px rgb(208, 255, 0); 17 | cursor: pointer; 18 | } 19 | 20 | /* 21 | .brandContainer:hover .brandTitle { 22 | color: rgb(255,223,0) !important; 23 | text-shadow: 1px 1px 1px rgb(84, 97, 91) !important; 24 | } 25 | */ 26 | 27 | .brandContainer h4{ 28 | letter-spacing: 3px; 29 | font-weight: lighter; 30 | font-size: 1.6em; 31 | color: rgba(240, 240, 240, .95); 32 | text-shadow: 1px 2px 1px rgba(50,20,50,0.05); 33 | } 34 | 35 | .brandContainer p { 36 | letter-spacing: 1px; 37 | font-weight: lighter; 38 | font-size: .6em; 39 | color: rgba(240, 240, 240, .85); 40 | text-shadow: 1px 2px 1px rgba(50,20,50,0.05); 41 | } 42 | 43 | /* Neon glow effect from here: http://enjoycss.com/gallery/text_effects/39 */ 44 | 45 | .brandTitle { 46 | -webkit-box-sizing: border-box; 47 | -moz-box-sizing: border-box; 48 | box-sizing: border-box; 49 | border: none; 50 | color: rgba(255,255,255,1); 51 | text-decoration: normal; 52 | text-align: center; 53 | -o-text-overflow: clip; 54 | text-overflow: clip; 55 | white-space: pre; 56 | text-shadow: 0 0 10px rgba(255,255,255,.75) , 0 0 20px rgba(255,255,255,.75) , 0 0 30px rgba(255,255,255,.75) , 0 0 40px #00ffff , 0 0 70px #00ffff , 0 0 80px #00ffff , 0 0 100px #00ffff !important; 57 | 58 | -webkit-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 59 | -moz-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 60 | -o-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 61 | transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 62 | display: inline-block; 63 | margin: 0; 64 | margin-left: auto; 65 | margin-right: auto; 66 | text-align: center; 67 | } 68 | 69 | .brandTitle:hover { 70 | text-shadow: 0 0 10px rgba(255,255,255,1) , 0 0 20px rgba(255,255,255,1) , 0 0 30px rgba(255,255,255,1) , 0 0 20px #ff00de , 0 0 40px #ff00de , 0 0 60px #ff00de , 0 0 80px #ff00de !important; 71 | 72 | } 73 | 74 | .brandSubtitle { 75 | margin-left: 20px; 76 | display: inline-block; 77 | text-shadow: 0 0 10px rgba(255,255,255,.3) , 0 0 20px rgba(255,255,255,.3) , 0 0 30px rgba(255,255,255,.3) , 0 0 20px #ff00de , 0 0 40px #ff00de , 0 0 60px #ff00de , 0 0 80px #ff00de !important; 78 | -webkit-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 79 | -moz-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 80 | -o-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 81 | transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1) !important; 82 | } -------------------------------------------------------------------------------- /frame/src/components/EntryCreate/EntryCreate.scss: -------------------------------------------------------------------------------- 1 | .entryCreateContainer { 2 | display: inline !important; 3 | } 4 | 5 | .formDisabled p { 6 | color: grey !important; 7 | } 8 | 9 | .ant-form-item { 10 | margin: 5px !important; 11 | } 12 | 13 | 14 | .ant-modal-content { 15 | border-radius: 3px !important; 16 | background: rgba(238, 238, 238, .93) !important; /* fallback for old browsers */ 17 | box-shadow: 0 0 0 1px rgba(204, 209, 212, 0.2); 18 | } 19 | 20 | .ant-modal-header { 21 | box-shadow: 0 0 0 1px rgba(204, 209, 212, 0.2); 22 | border-radius: 3px !important; 23 | background: rgba(238, 238, 238, .93) !important; /* fallback for old browsers */ 24 | } 25 | 26 | .ant-modal-title { 27 | font-size: 1.4em; 28 | height: 40px !important; 29 | } 30 | 31 | .entryTimestampBlock { 32 | top: 0 !important; 33 | left: 0 !important; 34 | color: rgba(65, 65, 65, 0.65); 35 | margin-left: 23px !important; 36 | margin-top: 40px !important; 37 | position: absolute !important; 38 | display: inline !important; 39 | } 40 | 41 | .modalFooterBlock { 42 | position: absolute; 43 | bottom: 0; 44 | left: 0; 45 | margin-bottom: 10px; 46 | margin-left: 10px; 47 | } -------------------------------------------------------------------------------- /frame/src/components/EntryEditForm/EntryEditForm.scss: -------------------------------------------------------------------------------- 1 | .entryCreateContainer { 2 | display: inline !important; 3 | } 4 | 5 | .formDisabled p { 6 | color: grey !important; 7 | } 8 | 9 | .ant-form-item { 10 | margin: 5px !important; 11 | } 12 | 13 | 14 | .ant-modal-content { 15 | border-radius: 3px !important; 16 | background: rgba(238, 238, 238, .93) !important; /* fallback for old browsers */ 17 | box-shadow: 0 0 0 1px rgba(204, 209, 212, 0.2); 18 | } 19 | 20 | .ant-modal-header { 21 | box-shadow: 0 0 0 1px rgba(204, 209, 212, 0.2); 22 | border-radius: 3px !important; 23 | background: rgba(238, 238, 238, .93) !important; /* fallback for old browsers */ 24 | } 25 | 26 | .ant-modal-title { 27 | font-size: 1.4em; 28 | height: 40px !important; 29 | } 30 | 31 | .entryTimestampBlock { 32 | top: 0 !important; 33 | left: 0 !important; 34 | color: rgba(65, 65, 65, 0.65); 35 | margin-left: 23px !important; 36 | margin-top: 40px !important; 37 | position: absolute !important; 38 | display: inline !important; 39 | } 40 | 41 | .modalFooterBlock { 42 | position: absolute; 43 | bottom: 0; 44 | left: 0; 45 | margin-bottom: 10px; 46 | margin-left: 10px; 47 | } -------------------------------------------------------------------------------- /frame/src/components/FJSONEditor/FJSONEditor.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import React, { Component } from 'react'; 3 | import JSONEditor from 'jsoneditor'; 4 | import 'jsoneditor/dist/jsoneditor.css'; 5 | import styles from './FJSONEditor.scss'; 6 | 7 | export default class FJSONEditor extends Component { 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | componentDidMount() { 13 | const options = { onChange: this.props.onChange }; 14 | this._container = document.getElementById('jsonEditor'); 15 | this._editor = new JSONEditor(this._container, options); 16 | this.props.editorRef(this._editor); 17 | this._editor.set(this.props.json); 18 | } 19 | 20 | componentWillReceiveProps(nextProps) { 21 | this._editor.set(nextProps.json); 22 | } 23 | 24 | render() { 25 | // console.log(this.props.json); 26 | return
; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /frame/src/components/FJSONEditor/FJSONEditor.scss: -------------------------------------------------------------------------------- 1 | .editor { 2 | height: 100%; 3 | width: 100%; 4 | overflow: auto !important; 5 | } 6 | 7 | .jsoneditor { 8 | border-radius: 3px; 9 | margin-top: 8px; 10 | font-size: .75em !important; 11 | border: none !important; 12 | overflow: auto !important; 13 | 14 | } 15 | 16 | #jsonEditor { 17 | border: none !important; 18 | box-shadow: none !important; 19 | border-radius: 3px !important; 20 | box-shadow: 1px 2px 2px 1px rgba(39, 39, 39, 0.85) !important; 21 | background: rgb(238, 238, 238) !important; /* fallback for old browsers */ 22 | min-height: 250px; 23 | max-height: 450px; 24 | overflow: auto !important; 25 | } 26 | 27 | .jsoneditor-menu { 28 | margin-top: 2px !important; 29 | border-radius: 3px; 30 | border-color: rgba(79, 176, 255, .85) !important; 31 | background-color: rgba(79, 176, 255, .85) !important; 32 | } 33 | 34 | .nav-bar-empty { 35 | display: none !important; 36 | } -------------------------------------------------------------------------------- /frame/src/components/Home/Home.scss: -------------------------------------------------------------------------------- 1 | .homeWrapper { 2 | margin: 0 !important; 3 | padding: 0 !important; 4 | width: 100% !important; 5 | height: 100% !important; 6 | background-color: rgba(250, 250, 250, 1.0) !important; 7 | overflow: auto !important; 8 | } 9 | 10 | .ant-collapse-item, .ant-collapse-item-active { 11 | background-color: transparent !important; 12 | } 13 | 14 | .datetime { 15 | top: 0 !important; 16 | right: 0 !important; 17 | margin: 25px !important; 18 | margin-right: 45px !important; 19 | margin-top: 10px !important; 20 | position: absolute !important; 21 | z-index: 100 !important; 22 | letter-spacing: 1px !important; 23 | } 24 | 25 | 26 | .libraryOverview { 27 | background-color: transparent !important; 28 | padding: 0 !important; 29 | margin: 0 !important; 30 | margin: 20px !important; 31 | // margin: 40px !important; 32 | } 33 | 34 | .libraryOverviewText { 35 | letter-spacing: 1px !important; 36 | font-weight: lighter !important; 37 | font-size: 1.5em !important; 38 | color: rgba(66, 66, 66, 0.9); 39 | text-align: center !important; 40 | } 41 | 42 | .askInput { 43 | background-color: transparent !important; 44 | padding: 0 !important; 45 | margin: 0 !important; 46 | margin: 20px !important; 47 | // margin: 40px !important; 48 | } 49 | 50 | .collapseTransparent { 51 | background-color: transparent !important; 52 | } 53 | 54 | .entriesChart { 55 | background-color: transparent !important; 56 | margin: 20px !important; 57 | // margin-right: -150px !important; 58 | } 59 | 60 | .tagsText { 61 | display: inline !important; 62 | } 63 | 64 | .titleText { 65 | display: inline !important; 66 | } 67 | 68 | .entriesVisualizedText { 69 | margin: 40px !important; 70 | font-weight: lighter !important; 71 | margin-right: 65px !important; 72 | font-size: 1.6em !important; 73 | letter-spacing: 1px !important; 74 | color: rgba(44, 44, 44, 0.9); 75 | text-align: center !important; 76 | } -------------------------------------------------------------------------------- /frame/src/components/SearchLibrary/SearchLibrary.scss: -------------------------------------------------------------------------------- 1 | .homeWrapper { 2 | margin: 0 !important; 3 | padding: 0 !important; 4 | width: 100% !important; 5 | height: 100% !important; 6 | background-color: rgba(250, 250, 250, 1.0) !important; 7 | overflow: auto !important; 8 | } 9 | 10 | .ant-collapse-item, .ant-collapse-item-active { 11 | background-color: transparent !important; 12 | } 13 | 14 | .datetime { 15 | top: 0 !important; 16 | right: 0 !important; 17 | margin: 25px !important; 18 | margin-right: 45px !important; 19 | margin-top: 10px !important; 20 | position: absolute !important; 21 | z-index: 100 !important; 22 | letter-spacing: 1px !important; 23 | } 24 | 25 | .askInput { 26 | background-color: transparent !important; 27 | padding: 0 !important; 28 | margin: 0 !important; 29 | margin: 20px !important; 30 | text-align: center !important; 31 | // margin: 40px !important; 32 | } 33 | 34 | .titleTextP { 35 | margin: 20px !important; 36 | letter-spacing: 1px !important; 37 | color: rgba(88, 88, 88, 1.0) !important; 38 | font-size: 1.25em !important; 39 | } 40 | 41 | .tagsHolder { 42 | text-align: center !important; 43 | width: calc(70% - 20px) !important; 44 | margin: 20px !important; 45 | margin-left: auto !important; 46 | margin-right: auto !important; 47 | // margin-left: 150px !important; 48 | } 49 | 50 | .collapseTransparent { 51 | background-color: transparent !important; 52 | } 53 | 54 | .entriesChart { 55 | background-color: transparent !important; 56 | margin: 20px !important; 57 | // margin-right: -150px !important; 58 | } 59 | 60 | .tagsText { 61 | display: inline !important; 62 | } 63 | 64 | .titleText { 65 | display: inline !important; 66 | } 67 | 68 | .entriesVisualizedText { 69 | margin: 40px !important; 70 | font-weight: lighter !important; 71 | margin-right: 65px !important; 72 | font-size: 1.6em !important; 73 | letter-spacing: 1px !important; 74 | color: rgba(44, 44, 44, 0.9); 75 | text-align: center !important; 76 | } -------------------------------------------------------------------------------- /frame/src/components/Settings/Settings.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import config from '../../data/config.json'; 3 | import React, { Component } from "react"; 4 | import PropTypes, { shape } from 'prop-types'; 5 | import {setState, getState} from '../../utils/session-state'; 6 | import { 7 | Row, Col, Layout, Menu, Breadcrumb, 8 | Icon, Button, Switch, Dropdown, message, 9 | Tooltip, Select, Drawer, Radio, Collapse, List, 10 | Divider, Form, Input 11 | } from 'antd'; 12 | 13 | /** 14 | * TODO: Eventually separate out the summarizer too and other analysis components, 15 | * since this class is getting massive. 16 | */ 17 | 18 | import { Wrapper, Tab, TabList, TabPanel} from 'react-aria-tabpanel'; 19 | 20 | import ReactJson from 'react-json-view'; 21 | 22 | import saveToDB from '../../utils/save-db'; 23 | import getFromDB from '../../utils/load-db'; 24 | import openDB from '../../utils/create-db'; 25 | import traverseEntriesById from '../../utils/entries-traversal'; 26 | import replaceEntry from '../../utils/replace-entry'; 27 | 28 | import './Settings.scss'; 29 | 30 | const RadioGroup = Radio.Group; 31 | const Panel = Collapse.Panel; 32 | 33 | /** Data library / source vars */ 34 | const savedSettings = config.savedSettings; 35 | const defaultFLib = savedSettings.defaultLibrary; 36 | 37 | export default class Settings extends Component { 38 | 39 | constructor(props) { 40 | super(props); 41 | this.state = { 42 | _isMounted: false, 43 | }; 44 | } 45 | 46 | componentDidMount() { 47 | this.setState({_isMounted: true}); 48 | } 49 | 50 | componentWillUnount() { 51 | this.setState({_isMounted: false}); 52 | } 53 | 54 | render() { 55 | return ( 56 |
57 | {/* Settingsssss */} 58 |
59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /frame/src/components/Settings/Settings.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/frame/src/components/Settings/Settings.scss -------------------------------------------------------------------------------- /frame/src/components/VisualizeLibrary/VisualizeLibrary.scss: -------------------------------------------------------------------------------- 1 | .homeWrapper { 2 | margin: 0 !important; 3 | padding: 0 !important; 4 | width: 100% !important; 5 | height: 100% !important; 6 | background-color: rgba(250, 250, 250, 1.0) !important; 7 | overflow: auto !important; 8 | } 9 | 10 | .ant-collapse-item, .ant-collapse-item-active { 11 | background-color: transparent !important; 12 | } 13 | 14 | .datetime { 15 | top: 0 !important; 16 | right: 0 !important; 17 | margin: 25px !important; 18 | margin-right: 45px !important; 19 | margin-top: 10px !important; 20 | position: absolute !important; 21 | z-index: 100 !important; 22 | letter-spacing: 1px !important; 23 | } 24 | 25 | .askInput { 26 | background-color: transparent !important; 27 | padding: 0 !important; 28 | margin: 0 !important; 29 | margin: 20px !important; 30 | // margin: 40px !important; 31 | } 32 | 33 | .collapseTransparent { 34 | background-color: transparent !important; 35 | } 36 | 37 | .entriesChart { 38 | background-color: transparent !important; 39 | margin: 20px !important; 40 | // margin-right: -150px !important; 41 | } 42 | 43 | .tagsText { 44 | display: inline !important; 45 | } 46 | 47 | .titleText { 48 | display: inline !important; 49 | } 50 | 51 | .entriesVisualizedText { 52 | margin: 40px !important; 53 | font-weight: lighter !important; 54 | margin-right: 65px !important; 55 | font-size: 1.6em !important; 56 | letter-spacing: 1px !important; 57 | color: rgba(44, 44, 44, 0.9); 58 | text-align: center !important; 59 | } -------------------------------------------------------------------------------- /frame/src/components/Visualizer/Visualizer.scss: -------------------------------------------------------------------------------- 1 | .FancyTabs-tabTextSmall { 2 | margin: 0 !important; 3 | padding: 0 !important; 4 | letter-spacing: 1px !important; 5 | font-size: 1.05vmax !important; 6 | margin-top: -10px !important; 7 | } 8 | 9 | .FancyTabs-tablistItemSmall { 10 | height: 32px !important; 11 | box-shadow: 0 1px 1px 0 rgba(53, 53, 53, 0.1) !important; 12 | margin-top: -18px !important; 13 | background-color: rgba(239, 244, 248, 0.923) !important; 14 | } 15 | 16 | .leftViz { 17 | top: 0 !important; 18 | left: 0 !important; 19 | float: left !important; 20 | margin: 0 !important; 21 | padding: 0 !important; 22 | margin-left: 150px !important; 23 | margin-right: 50px !important; 24 | padding: 0 !important; 25 | max-width: calc(55% - 20px) !important; 26 | max-height: calc(75% - 20px) !important; 27 | text-align: center !important; 28 | } 29 | 30 | .rightViz { 31 | top: 0 !important; 32 | right: 0 !important; 33 | margin: 0 !important; 34 | float: right !important; 35 | margin-right: 150px !important; 36 | padding: 0 !important; 37 | max-width: calc(55% - 20px) !important; 38 | max-height: calc(75% - 20px) !important; 39 | text-align: center !important; 40 | } 41 | 42 | .centerViz { 43 | margin: 0 !important; 44 | padding: 0 !important; 45 | text-align: center !important; 46 | margin-left: auto !important; 47 | margin-right: auto !important; 48 | max-width: calc(65% - 20px) !important; 49 | // max-height: calc(80% - 20px) !important; 50 | } 51 | 52 | .leftViz tspan { 53 | font-size: .9vmax !important; 54 | } 55 | 56 | .rightViz tspan { 57 | font-size: .9vmax !important; 58 | } 59 | 60 | .centerViz tspan { 61 | font-size: .9vmax !important; 62 | } 63 | 64 | .innerContentTextCenter { 65 | text-align: center !important; 66 | margin: 0 !important; 67 | padding: 0 !important; 68 | margin-left: auto !important; 69 | margin-right: auto !important; 70 | letter-spacing: 1px !important; 71 | font-size: 1.0vmax !important; 72 | } 73 | 74 | 75 | .FancyTabs-tablistHigher { 76 | list-style-type: none; 77 | margin: 0; 78 | padding: 0; 79 | margin-top: -20px !important; 80 | margin-left: auto !important; 81 | margin-right: auto !important; 82 | text-align: center !important; 83 | width: 100% !important; 84 | } -------------------------------------------------------------------------------- /frame/src/components/vendor/basic.scss: -------------------------------------------------------------------------------- 1 | .md-block-header-one { 2 | font-size: 2em; 3 | } 4 | .md-block-header-two { 5 | font-size: 1.7em; 6 | } 7 | .md-block-header-three { 8 | font-size: 1.3em; 9 | } 10 | .md-block-header-four { 11 | font-size: 1em; 12 | } 13 | .md-block-header-five { 14 | font-size: 0.8em; 15 | } 16 | .md-block-header-six { 17 | font-size: 0.7em; 18 | } 19 | 20 | .md-block-header-one, 21 | .md-block-header-two, 22 | .md-block-header-three, 23 | .md-block-header-four, 24 | .md-block-header-five, 25 | .md-block-header-six { 26 | margin-bottom: 5px; 27 | } 28 | 29 | .md-block-blockquote { 30 | margin: 0; 31 | padding-left: 15px; 32 | border-left: 5px solid #4CA8DE; 33 | padding: 10px 0 10px 20px; 34 | background-color: #E2F2FF; 35 | font-size: 1.1em; 36 | } 37 | 38 | .md-block-image { 39 | margin: 0 0 10px 0; 40 | 41 | img { 42 | width: 100%; 43 | } 44 | 45 | figcaption { 46 | text-align: center; 47 | font-size: 0.9em; 48 | } 49 | } 50 | 51 | .md-block-todo { 52 | margin: 10px 0 10px 0; 53 | 54 | input[type=checkbox] { 55 | float: left; 56 | position: relative; 57 | top: 0px; 58 | left: -2px; 59 | } 60 | p { 61 | margin-left: 18px; 62 | } 63 | } 64 | 65 | .md-block-unordered-list-item, .md-block-ordered-list-item { 66 | padding-left: 20px; 67 | 68 | li { 69 | margin-bottom: 5px; 70 | } 71 | } 72 | 73 | .md-block-atomic-embed { 74 | margin: 10px 0; 75 | } 76 | 77 | .md-block-atomic-break { 78 | hr { 79 | max-width: 100px; 80 | border: 2px solid #ccc; 81 | } 82 | } 83 | 84 | .md-inline-code { 85 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; 86 | margin: 4px 0px; 87 | font-size: 0.9em; 88 | padding: 1px 3px; 89 | color: rgb(85, 85, 85); 90 | background-color: rgb(252, 252, 252); 91 | border-width: 1px; 92 | border-style: solid; 93 | border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(187, 187, 187); 94 | border-image: initial; 95 | border-radius: 3px; 96 | box-shadow: rgb(187, 187, 187) 0px -1px 0px inset; 97 | } 98 | 99 | 100 | .md-inline-link { 101 | color: #08c; 102 | 103 | &:visited { 104 | color: #08c; 105 | } 106 | } 107 | 108 | .md-inline-highlight { 109 | background: yellow; 110 | display: inline; 111 | padding: 2px 4px; 112 | } 113 | 114 | p { 115 | &.md-block-block-quote-caption { 116 | 117 | &::before { 118 | content: '\2013'; 119 | color: #999; 120 | float: left; 121 | font-weight: bold; 122 | display: inline; 123 | margin-right: 10px; 124 | } 125 | margin-top: 0; 126 | font-size: 0.8em; 127 | padding-top: 5px; 128 | padding-bottom: 5px; 129 | padding-left: 10px; 130 | background: #fafafa; 131 | } 132 | } 133 | 134 | .md-block-code-container { 135 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 136 | white-space: pre; 137 | word-spacing: normal; 138 | word-break: normal; 139 | word-wrap: normal; 140 | background-color: rgba(0, 0, 0, 0.05); 141 | font-size: 16px; 142 | padding: 20px; 143 | margin: 1em 0px; 144 | 145 | > pre { 146 | margin-top: 0; 147 | padding-top: 0; 148 | } 149 | } 150 | 151 | .md-block-code-block { 152 | white-space: pre-wrap; 153 | word-wrap: break-word; 154 | } 155 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/LinkEditComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { getVisibleSelectionRect } from 'draft-js'; 4 | 5 | const getRelativeParent = (element) => { 6 | if (!element) { 7 | return null; 8 | } 9 | 10 | const position = window.getComputedStyle(element).getPropertyValue('position'); 11 | if (position !== 'static') { 12 | return element; 13 | } 14 | 15 | return getRelativeParent(element.parentElement); 16 | }; 17 | 18 | export default class LinkEditComponent extends React.Component { 19 | 20 | static propTypes = { 21 | editorState: PropTypes.object.isRequired, 22 | url: PropTypes.string.isRequired, 23 | blockKey: PropTypes.string.isRequired, 24 | entityKey: PropTypes.string.isRequired, 25 | removeLink: PropTypes.func.isRequired, 26 | editLink: PropTypes.func.isRequired, 27 | }; 28 | 29 | constructor(props) { 30 | super(props); 31 | 32 | this.state = { 33 | position: {}, 34 | }; 35 | this.renderedOnce = false; 36 | } 37 | 38 | componentDidMount() { 39 | setTimeout(this.calculatePosition, 0); 40 | } 41 | 42 | shouldComponentUpdate(nextProps, nextState) { 43 | if (this.renderedOnce) { 44 | const { blockKey, entityKey } = this.props; 45 | const ret = !this.hasPosition(nextState.position) || blockKey !== nextProps.blockKey || entityKey !== nextProps.entityKey; 46 | if (ret) { 47 | this.renderedOnce = false; 48 | } 49 | return ret; 50 | } 51 | this.renderedOnce = true; 52 | return true; 53 | } 54 | 55 | componentDidUpdate() { 56 | setTimeout(this.calculatePosition, 0); 57 | } 58 | 59 | hasPosition = (position) => { 60 | if (Object.keys(this.state.position).length === 0) { 61 | return false; 62 | } 63 | const { top, left } = this.state.position; 64 | return position.top === top && position.left === left; 65 | }; 66 | 67 | calculatePosition = () => { 68 | if (!this.toolbar) { 69 | return; 70 | } 71 | const relativeParent = getRelativeParent(this.toolbar.parentElement); 72 | const relativeRect = relativeParent ? relativeParent.getBoundingClientRect() : window.document.body.getBoundingClientRect(); 73 | const selectionRect = getVisibleSelectionRect(window); 74 | if (!selectionRect) { 75 | return; 76 | } 77 | const position = { 78 | top: (selectionRect.top - relativeRect.top) + 35, 79 | left: (selectionRect.left - relativeRect.left) + (selectionRect.width / 2), 80 | transform: 'translate(-50%) scale(1)', 81 | }; 82 | this.setState({ position }); 83 | }; 84 | 85 | removeLink = (e) => { 86 | e.preventDefault(); 87 | e.stopPropagation(); 88 | this.props.removeLink(this.props.blockKey, this.props.entityKey); 89 | }; 90 | 91 | editLink = (e) => { 92 | e.preventDefault(); 93 | e.stopPropagation(); 94 | this.props.editLink(this.props.blockKey, this.props.entityKey); 95 | }; 96 | 97 | render() { 98 | let url = this.props.url; 99 | if (url.length > 30) { 100 | url = `${url.slice(0, 30)}...`; 101 | } 102 | return ( 103 |
{ 107 | this.toolbar = element; 108 | }} 109 | > 110 | {url} 111 | 112 | 113 |
114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/addbutton.scss: -------------------------------------------------------------------------------- 1 | $add-btn-width: 30px; 2 | 3 | 4 | .md-side-toolbar { 5 | display: flex; 6 | position: absolute; 7 | z-index: 1; 8 | left: -35px; 9 | top: 0; 10 | transition: all 0.2s ease; 11 | } 12 | 13 | .md-sb-button { 14 | background: none; 15 | border: 1px solid #5b5b5b; 16 | color: #6D6D6D; 17 | cursor: pointer; 18 | height: $add-btn-width; 19 | width: $add-btn-width; 20 | border-radius: $add-btn-width/2; 21 | font-weight: bold; 22 | font-size: 20px; 23 | margin-right: 2px; 24 | text-align: center; 25 | transition: all 0.2s ease; 26 | 27 | &:focus { 28 | outline: none; 29 | border-color: #08c; 30 | color: #08c; 31 | } 32 | 33 | &:hover { 34 | color: green; 35 | } 36 | 37 | &.md-sb-img-button { 38 | background: none; 39 | background-color: white; 40 | } 41 | 42 | svg path { 43 | stroke-width: 0; 44 | fill: #545454; 45 | } 46 | } 47 | 48 | .md-add-button { 49 | &.md-open-button { 50 | transform: rotate(45deg); 51 | } 52 | } 53 | 54 | .md-add-btn-anim-appear { 55 | transform: translate3d(-38px, 0px, 0px); 56 | opacity: 0; 57 | } 58 | 59 | .md-add-btn-anim-appear.md-add-btn-anim-appear-active { 60 | transform: translate3d(0px, 0px, 0px); 61 | opacity: 1; 62 | transition: all .5s ease-in; 63 | } 64 | 65 | .md-add-btn-anim-enter { 66 | transform: translate3d(-38px, 0px, 0px); 67 | opacity: 0; 68 | } 69 | 70 | .md-add-btn-anim-enter.md-add-btn-anim-enter-active { 71 | opacity: 1; 72 | transform: translate3d(0px, 0px, 0px); 73 | transition: all 500ms ease-in; 74 | } 75 | 76 | .md-add-btn-anim-exit { 77 | opacity: 1; 78 | } 79 | 80 | .md-add-btn-anim-exit.md-add-btn-anim-exit-active { 81 | opacity: 0.01; 82 | transition: opacity 300ms ease-in; 83 | } 84 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/atomic.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // import './atomic.scss'; 3 | 4 | import React from 'react'; 5 | 6 | const AtomicBlock = (props) => { 7 | const content = props.getEditorState().getCurrentContent(); 8 | const entity = content.getEntity(props.block.getEntityAt(0)); 9 | const data = entity.getData(); 10 | const type = entity.getType(); 11 | if (type === 'image') { 12 | return ( 13 |
14 | 15 |
16 | 17 |
18 |
19 | ); 20 | } 21 | return

No supported block for {type}

; 22 | }; 23 | 24 | AtomicBlock.propTypes = { 25 | block: PropTypes.object, 26 | getEditorState: PropTypes.func, 27 | }; 28 | 29 | export default AtomicBlock; 30 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/atomic.scss: -------------------------------------------------------------------------------- 1 | $control-btn-width: 22px; 2 | 3 | .md-block-atomic { 4 | margin: 0; 5 | img { 6 | width: 100%; 7 | border: 1px solid #eee; 8 | box-sizing: border-box; 9 | } 10 | } 11 | 12 | .md-block-atomic-wrapper { 13 | position: relative; 14 | } 15 | 16 | .md-block-atomic-controls { 17 | display: none; 18 | position: absolute; 19 | top: 0; 20 | right: 0; 21 | transition: all 0.2s ease; 22 | 23 | button { 24 | display: inline-block; 25 | background-color: #EAEAEA; 26 | border: none; 27 | color: #6D6D6D; 28 | cursor: pointer; 29 | height: $control-btn-width; 30 | width: $control-btn-width; 31 | border-radius: $control-btn-width/2; 32 | position: absolute; 33 | z-index: 1; 34 | left: -27px; 35 | font-weight: bold; 36 | text-align: center; 37 | transition: all 0.2s ease; 38 | 39 | &:focus { 40 | outline: none; 41 | border-color: #08c; 42 | color: #08c; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/blockquotecaption.js: -------------------------------------------------------------------------------- 1 | // import './blockquotecaption.scss'; 2 | 3 | import React from 'react'; 4 | import { EditorBlock } from 'draft-js'; 5 | 6 | export default (props) => ( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/blockquotecaption.scss: -------------------------------------------------------------------------------- 1 | .md-block-quote { 2 | cite { 3 | display: block; 4 | margin: 0; 5 | 6 | &::before { 7 | content: '\2013'; 8 | color: #999; 9 | float: left; 10 | font-weight: bold; 11 | display: inline; 12 | margin-right: 10px; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/break.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default () => ( 4 |
5 | ); 6 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/caption.js: -------------------------------------------------------------------------------- 1 | // import './caption.scss'; 2 | 3 | import React from 'react'; 4 | import { EditorBlock } from 'draft-js'; 5 | 6 | export default (props) => ( 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/caption.scss: -------------------------------------------------------------------------------- 1 | .md-block-caption { 2 | display: block; 3 | position: relative; 4 | font-style: normal; 5 | padding: 10px 0; 6 | font-family: 'Hoefler Text', 'Georgia', serif; 7 | margin: 0 0 20px 0; 8 | background-color: #F7F7F7; 9 | border-radius: 5px; 10 | line-height: 1.2em; 11 | 12 | &::before { 13 | content: '“'; 14 | color: #C6DFFF; 15 | display: inline; 16 | position: absolute; 17 | left: -25px; 18 | top: -5px; 19 | font-size: 3em; 20 | } 21 | 22 | .public-DraftStyleDefault-ltr { 23 | text-align: center; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/image.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { EditorBlock, EditorState, SelectionState } from 'draft-js'; 5 | 6 | import { getCurrentBlock } from '../../model/'; 7 | 8 | class ImageBlock extends React.Component { 9 | 10 | static propTypes = { 11 | block: PropTypes.object, 12 | blockProps: PropTypes.object, 13 | }; 14 | 15 | focusBlock = () => { 16 | const { block, blockProps } = this.props; 17 | const { getEditorState, setEditorState } = blockProps; 18 | const key = block.getKey(); 19 | const editorState = getEditorState(); 20 | const currentblock = getCurrentBlock(editorState); 21 | if (currentblock.getKey() === key) { 22 | return; 23 | } 24 | const newSelection = new SelectionState({ 25 | anchorKey: key, 26 | focusKey: key, 27 | anchorOffset: 0, 28 | focusOffset: 0, 29 | }); 30 | setEditorState(EditorState.forceSelection(editorState, newSelection)); 31 | }; 32 | 33 | render() { 34 | const { block } = this.props; 35 | const data = block.getData(); 36 | const src = data.get('src'); 37 | if (src !== null) { 38 | return ( 39 |
40 |
41 | 42 |
43 |
44 | 45 |
46 |
47 | ); 48 | } 49 | return ; 50 | } 51 | } 52 | 53 | export default ImageBlock; 54 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/image.scss: -------------------------------------------------------------------------------- 1 | figure.md-block-image { 2 | // margin: 0; 3 | margin: 10px 0; 4 | background: #fbfbfb; 5 | img { 6 | cursor: default; 7 | max-width: 100%; 8 | border: 1px solid #eee; 9 | box-sizing: border-box; 10 | 11 | &.is-selected { 12 | box-shadow: 0 0 0 3px #02b875; 13 | } 14 | } 15 | 16 | figcaption { 17 | display: block; 18 | font-size: 14px; 19 | line-height: 1.4; 20 | color: rgba(0,0,0,.6); 21 | letter-spacing: 0; 22 | font-weight: 300; 23 | font-style: normal; 24 | text-align: center; 25 | padding: 5px 0; 26 | 27 | .public-DraftStyleDefault-block { 28 | text-align: center; 29 | } 30 | } 31 | 32 | .md-block-image-inner-container { 33 | position: relative; 34 | } 35 | .md-block-image-toolbar-container { 36 | position: absolute; 37 | top: 0; 38 | right: 10px; 39 | cursor: pointer; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/text.js: -------------------------------------------------------------------------------- 1 | // import './text.scss'; 2 | 3 | import React from 'react'; 4 | import { EditorBlock } from 'draft-js'; 5 | 6 | // export default class Paragraph extends Component { 7 | // render(){ 8 | // return ( 9 | // 10 | // ); 11 | // } 12 | // } 13 | 14 | export default (props) => ; 15 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/text.scss: -------------------------------------------------------------------------------- 1 | .public-DraftEditor-content { 2 | .md-block-paragraph { 3 | margin: 20px 0; 4 | 5 | &:first-child { 6 | margin-top: 0; 7 | } 8 | 9 | &:last-child { 10 | margin-bottom: 0; 11 | } 12 | } 13 | } 14 | 15 | .md-block-checkbox { 16 | input[type=checkbox] { 17 | float: left; 18 | margin-right: 10px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/todo.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // import './todo.scss'; 3 | 4 | import React from 'react'; 5 | import { EditorBlock } from 'draft-js'; 6 | 7 | import { updateDataOfBlock } from '../../model/'; 8 | 9 | export default class TodoBlock extends React.Component { 10 | constructor(props) { 11 | super(props); 12 | this.updateData = this.updateData.bind(this); 13 | } 14 | 15 | updateData() { 16 | const { block, blockProps } = this.props; 17 | const { setEditorState, getEditorState } = blockProps; 18 | const data = block.getData(); 19 | const checked = (data.has('checked') && data.get('checked') === true); 20 | const newData = data.set('checked', !checked); 21 | setEditorState(updateDataOfBlock(getEditorState(), block, newData)); 22 | } 23 | 24 | render() { 25 | const data = this.props.block.getData(); 26 | const checked = data.get('checked') === true; 27 | return ( 28 |
29 | 30 | 31 | 32 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | 39 | TodoBlock.propTypes = { 40 | block: PropTypes.object, 41 | blockProps: PropTypes.object, 42 | }; 43 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocks/todo.scss: -------------------------------------------------------------------------------- 1 | .md-block-todo { 2 | 3 | input[type=checkbox] { 4 | cursor: pointer; 5 | float: left; 6 | position: relative; 7 | top: 4px; 8 | left: -4px; 9 | } 10 | 11 | .public-DraftStyleDefault-block { 12 | margin-left: 18px; 13 | } 14 | 15 | .md-block-todo-completed { 16 | color: #949494; 17 | text-decoration: line-through; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/blocktoolbar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import { RichUtils } from 'draft-js'; 4 | 5 | import StyleButton from './stylebutton'; 6 | 7 | 8 | const BlockToolbar = (props) => { 9 | if (props.buttons.length < 1) { 10 | return null; 11 | } 12 | const { editorState } = props; 13 | const blockType = RichUtils.getCurrentBlockType(editorState); 14 | return ( 15 |
16 | {props.buttons.map((type) => { 17 | const iconLabel = {}; 18 | iconLabel.label = type.label; 19 | return ( 20 | 28 | ); 29 | })} 30 |
31 | ); 32 | }; 33 | 34 | BlockToolbar.propTypes = { 35 | buttons: PropTypes.array, 36 | editorState: PropTypes.object.isRequired, 37 | onToggle: PropTypes.func, 38 | }; 39 | 40 | export default BlockToolbar; 41 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/customrenderer.js: -------------------------------------------------------------------------------- 1 | import QuoteCaptionBlock from './blocks/blockquotecaption'; 2 | import CaptionBlock from './blocks/caption'; 3 | import AtomicBlock from './blocks/atomic'; 4 | import TodoBlock from './blocks/todo'; 5 | import ImageBlock from './blocks/image'; 6 | import BreakBlock from './blocks/break'; 7 | 8 | import { Block } from '../util/constants'; 9 | 10 | export default (setEditorState, getEditorState) => (contentBlock) => { 11 | // console.log(editorState, onChange); 12 | const type = contentBlock.getType(); 13 | switch (type) { 14 | case Block.BLOCKQUOTE_CAPTION: return { 15 | component: QuoteCaptionBlock, 16 | }; 17 | case Block.CAPTION: return { 18 | component: CaptionBlock, 19 | }; 20 | case Block.ATOMIC: return { 21 | component: AtomicBlock, 22 | editable: false, 23 | props: { 24 | getEditorState, 25 | }, 26 | }; 27 | case Block.TODO: return { 28 | component: TodoBlock, 29 | props: { 30 | setEditorState, 31 | getEditorState, 32 | }, 33 | }; 34 | case Block.IMAGE: return { 35 | component: ImageBlock, 36 | props: { 37 | setEditorState, 38 | getEditorState, 39 | }, 40 | }; 41 | case Block.BREAK: return { 42 | component: BreakBlock, 43 | editable: false, 44 | }; 45 | default: return null; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/entities/link.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { Entity } from '../../util/constants'; 5 | 6 | 7 | export const findLinkEntities = (contentBlock, callback, contentState) => { 8 | contentBlock.findEntityRanges( 9 | (character) => { 10 | const entityKey = character.getEntity(); 11 | return ( 12 | entityKey !== null && 13 | contentState.getEntity(entityKey).getType() === Entity.LINK 14 | ); 15 | }, 16 | callback 17 | ); 18 | }; 19 | 20 | const Link = (props) => { 21 | const { contentState, entityKey } = props; 22 | const { url } = contentState.getEntity(entityKey).getData(); 23 | return ( 24 | {props.children} 31 | ); 32 | }; 33 | 34 | Link.propTypes = { 35 | children: PropTypes.node, 36 | entityKey: PropTypes.string, 37 | contentState: PropTypes.object.isRequired, 38 | }; 39 | 40 | export default Link; 41 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/inlinetoolbar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import StyleButton from './stylebutton'; 5 | 6 | 7 | const InlineToolbar = (props) => { 8 | if (props.buttons.length < 1) { 9 | return null; 10 | } 11 | const currentStyle = props.editorState.getCurrentInlineStyle(); 12 | return ( 13 |
14 | {props.buttons.map(type => { 15 | const iconLabel = {}; 16 | iconLabel.label = type.label; 17 | return ( 18 | 26 | ); 27 | })} 28 |
29 | ); 30 | }; 31 | 32 | InlineToolbar.propTypes = { 33 | buttons: PropTypes.array, 34 | editorState: PropTypes.object.isRequired, 35 | onToggle: PropTypes.func, 36 | }; 37 | 38 | export default InlineToolbar; 39 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/sides/break.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { addNewBlock } from '../../model'; 5 | import { Block } from '../../util/constants'; 6 | 7 | export default class BreakButton extends React.Component { 8 | 9 | constructor(props) { 10 | super(props); 11 | 12 | this.onClick = this.onClick.bind(this); 13 | } 14 | 15 | onClick() { 16 | this.props.setEditorState(addNewBlock( 17 | this.props.getEditorState(), 18 | Block.BREAK 19 | )); 20 | } 21 | 22 | render() { 23 | return ( 24 | 27 | ); 28 | } 29 | } 30 | 31 | BreakButton.propTypes = { 32 | setEditorState: PropTypes.func, 33 | getEditorState: PropTypes.func, 34 | close: PropTypes.func, 35 | }; 36 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/sides/image.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { addNewBlock } from '../../model'; 5 | import { Block } from '../../util/constants'; 6 | 7 | export default class ImageButton extends React.Component { 8 | 9 | static propTypes = { 10 | setEditorState: PropTypes.func, 11 | getEditorState: PropTypes.func, 12 | close: PropTypes.func, 13 | }; 14 | 15 | constructor(props) { 16 | super(props); 17 | 18 | this.onClick = this.onClick.bind(this); 19 | this.onChange = this.onChange.bind(this); 20 | } 21 | 22 | onClick() { 23 | this.input.value = null; 24 | this.input.click(); 25 | } 26 | 27 | 28 | /* 29 | This is an example of how an image button can be added 30 | on the side control. This Button handles the image addition locally 31 | by creating an object url. You can override this method to upload 32 | images to your server first, then get the image url in return and then 33 | add to the editor. 34 | */ 35 | onChange(e) { 36 | // e.preventDefault(); 37 | const file = e.target.files[0]; 38 | if (file.type.indexOf('image/') === 0) { 39 | // console.log(this.props.getEditorState()); 40 | // eslint-disable-next-line no-undef 41 | const src = URL.createObjectURL(file); 42 | this.props.setEditorState(addNewBlock( 43 | this.props.getEditorState(), 44 | Block.IMAGE, { 45 | src, 46 | } 47 | )); 48 | } 49 | this.props.close(); 50 | } 51 | 52 | render() { 53 | return ( 54 | 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /frame/src/components/vendor/components/stylebutton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { HYPERLINK } from '../util/constants.js'; 5 | 6 | export default class StyleButton extends React.Component { 7 | constructor(props) { 8 | super(props); 9 | this.onToggle = (e) => { 10 | e.preventDefault(); 11 | this.props.onToggle(this.props.style); 12 | }; 13 | } 14 | 15 | render() { 16 | if (this.props.style === HYPERLINK) { 17 | return null; 18 | } 19 | let className = 'md-RichEditor-styleButton'; 20 | if (this.props.active) { 21 | className += ' md-RichEditor-activeButton'; 22 | } 23 | className += ` md-RichEditor-styleButton-${this.props.style.toLowerCase()}`; 24 | return ( 25 | 30 | {this.props.icon ? : this.props.label} 31 | 32 | ); 33 | } 34 | } 35 | 36 | 37 | StyleButton.propTypes = { 38 | onToggle: PropTypes.func, 39 | style: PropTypes.string, 40 | active: PropTypes.bool, 41 | icon: PropTypes.string, 42 | label: PropTypes.oneOfType([ 43 | PropTypes.string, 44 | PropTypes.element, 45 | PropTypes.object, 46 | ]), 47 | description: PropTypes.string, 48 | }; 49 | -------------------------------------------------------------------------------- /frame/src/components/vendor/index.js: -------------------------------------------------------------------------------- 1 | import Editor from './editor'; 2 | 3 | import beforeInput, { StringToTypeMap } from './util/beforeinput'; 4 | import RenderMap from './util/rendermap'; 5 | import Link, { findLinkEntities } from './components/entities/link'; 6 | import keyBindingFn from './util/keybinding'; 7 | import rendererFn from './components/customrenderer'; 8 | import customStyleMap from './util/customstylemap'; 9 | import createEditorState from './model/content'; 10 | 11 | import QuoteCaptionBlock from './components/blocks/blockquotecaption'; 12 | import CaptionBlock from './components/blocks/caption'; 13 | import AtomicBlock from './components/blocks/atomic'; 14 | import TodoBlock from './components/blocks/todo'; 15 | import ImageBlock from './components/blocks/image'; 16 | import BreakBlock from './components/blocks/break'; 17 | 18 | import ImageSideButton from './components/sides/image'; 19 | import BreakSideButton from './components/sides/break'; 20 | 21 | export { Block, Inline, Entity, HANDLED, NOT_HANDLED } from './util/constants'; 22 | export { BLOCK_BUTTONS, INLINE_BUTTONS } from './components/toolbar'; 23 | 24 | export { 25 | getDefaultBlockData, 26 | getCurrentBlock, 27 | addNewBlock, 28 | resetBlockWithType, 29 | updateDataOfBlock, 30 | addNewBlockAt, 31 | } from './model'; 32 | 33 | // eslint-disable-next-line no-undef 34 | // export const _version = __VERSION__; 35 | 36 | export { 37 | Editor, 38 | createEditorState, 39 | StringToTypeMap, 40 | RenderMap, 41 | Link, 42 | findLinkEntities, 43 | beforeInput, 44 | customStyleMap, 45 | keyBindingFn, 46 | rendererFn, 47 | QuoteCaptionBlock, 48 | CaptionBlock, 49 | AtomicBlock, 50 | TodoBlock, 51 | ImageBlock, 52 | BreakBlock, 53 | ImageSideButton, 54 | BreakSideButton, 55 | }; 56 | 57 | export default Editor; 58 | -------------------------------------------------------------------------------- /frame/src/components/vendor/index.scss: -------------------------------------------------------------------------------- 1 | .md-RichEditor-root { 2 | background: #fff; 3 | box-sizing: border-box; 4 | //font-family: 'Georgia', serif; 5 | padding: 15px 30px; 6 | position: relative; 7 | line-height: 1.4em; 8 | } 9 | 10 | 11 | .md-RichEditor-editor { 12 | cursor: text; 13 | margin-top: 10px; 14 | position: relative; 15 | margin: 0 auto; 16 | 17 | h3 { 18 | font-size: 1.3em; 19 | margin: 1.2em 0; 20 | } 21 | } 22 | 23 | .md-RichEditor-editor .public-DraftEditorPlaceholder-root, 24 | .md-RichEditor-editor .public-DraftEditor-content { 25 | margin: 0px -15px -15px; 26 | padding: 15px; 27 | } 28 | 29 | .md-RichEditor-editor .public-DraftEditor-content { 30 | min-height: 100px; 31 | } 32 | 33 | .md-RichEditor-hidePlaceholder .public-DraftEditorPlaceholder-root { 34 | display: none; 35 | } 36 | 37 | .md-RichEditor-editor .md-RichEditor-blockquote { 38 | border-left: 5px solid #4CA8DE; 39 | color: #555; 40 | //font-family: 'Hoefler Text', 'Georgia', serif; 41 | font-size: 1.2em; 42 | margin: 0; 43 | padding: 10px 0 10px 20px; 44 | background-color: #E2F2FF; 45 | } 46 | 47 | .md-RichEditor-blockquote { 48 | a { 49 | text-decoration: underline; 50 | } 51 | } 52 | 53 | .public-DraftEditor-content { 54 | .md-block:first-child { 55 | margin-top: 0; 56 | padding-top: 0; 57 | } 58 | } 59 | 60 | .md-RichEditor-editor .public-DraftStyleDefault-pre { 61 | background-color: rgba(0, 0, 0, 0.05); 62 | //font-family: 'Inconsolata', 'Menlo', 'Consolas', monospace; 63 | font-size: 16px; 64 | padding: 20px; 65 | } 66 | 67 | .public-DraftStyleDefault-unorderedListItem, 68 | .public-DraftStyleDefault-orderedListItem { 69 | margin-bottom: 10px; 70 | } 71 | 72 | .md-editor-action { 73 | position: fixed; 74 | top: 5px; 75 | left: 5px; 76 | 77 | button { 78 | display: block; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /frame/src/components/vendor/model/content.js: -------------------------------------------------------------------------------- 1 | import { 2 | EditorState, 3 | convertFromRaw, 4 | CompositeDecorator, 5 | ContentState, 6 | } from 'draft-js'; 7 | 8 | import Link, { findLinkEntities } from '../components/entities/link'; 9 | 10 | 11 | const defaultDecorators = new CompositeDecorator([ 12 | { 13 | strategy: findLinkEntities, 14 | component: Link, 15 | }, 16 | ]); 17 | 18 | 19 | const createEditorState = (content = null, decorators = defaultDecorators) => { 20 | if (content === null) { 21 | return EditorState.createEmpty(decorators); 22 | } 23 | let contentState = null; 24 | if (typeof content === 'string') { 25 | contentState = ContentState.createFromText(content); 26 | } else { 27 | contentState = convertFromRaw(content); 28 | } 29 | return EditorState.createWithContent(contentState, decorators); 30 | }; 31 | 32 | export default createEditorState; 33 | -------------------------------------------------------------------------------- /frame/src/components/vendor/model/content.spec.js: -------------------------------------------------------------------------------- 1 | import { convertToRaw, CompositeDecorator } from 'draft-js'; 2 | import createEditorState from './content'; 3 | import { Block } from '../util/constants'; 4 | 5 | import preData from '../../docs/data.json'; 6 | import Link, { findLinkEntities } from '../components/entities/link'; 7 | 8 | describe('createEditorState', () => { 9 | const es = createEditorState(); 10 | 11 | it('creates empty editorState when no argument or null is passed', () => { 12 | const raw = convertToRaw(es.getCurrentContent()); 13 | expect(raw.blocks).to.be.instanceof(Array); 14 | expect(raw.blocks[0].type).to.equal(Block.UNSTYLED); 15 | expect(raw.blocks[0].text).to.equal(''); 16 | expect(raw.blocks[0]).to.include.keys('data', 'key'); 17 | }); 18 | 19 | it('adds link decorator by default in CompositeDecorator', () => { 20 | expect(es.getDecorator()).to.be.instanceof(CompositeDecorator); 21 | expect(es.getDecorator()._decorators.length).to.equal(1); 22 | expect(es.getDecorator()._decorators[0]).to.deep.equal({ 23 | strategy: findLinkEntities, 24 | component: Link, 25 | }); 26 | }); 27 | 28 | const esContent = createEditorState(preData); 29 | 30 | it('fills data from provided json', () => { 31 | const blocks = esContent.getCurrentContent().getBlockMap(); 32 | expect(blocks.size).to.be.above(1); 33 | 34 | expect(esContent.getDecorator()).to.be.instanceof(CompositeDecorator); 35 | expect(esContent.getDecorator()._decorators.length).to.equal(1); 36 | expect(esContent.getDecorator()._decorators[0]).to.deep.equal({ 37 | strategy: findLinkEntities, 38 | component: Link, 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/beforeinput.js: -------------------------------------------------------------------------------- 1 | import { resetBlockWithType, getCurrentBlock } from '../model'; 2 | import { Block, HANDLED, NOT_HANDLED } from './constants'; 3 | 4 | 5 | /* 6 | This is a key value pair where the key is the string that is input while typing. 7 | While typing in an empty block, if the entered text matches any of the keys in 8 | this dictionary, that particular block's type will be changed to the value 9 | associated with that key. 10 | */ 11 | export const StringToTypeMap = { 12 | '--': `${Block.BLOCKQUOTE}:${Block.BLOCKQUOTE_CAPTION}:${Block.CAPTION}`, 13 | '> ': Block.BLOCKQUOTE, 14 | '*.': Block.UL, 15 | '* ': Block.UL, 16 | '- ': Block.UL, 17 | '1.': Block.OL, 18 | '# ': Block.H1, 19 | '##': Block.H2, 20 | '==': Block.UNSTYLED, 21 | '[]': Block.TODO, 22 | }; 23 | 24 | 25 | /* 26 | This function is called before text is input in a block in `draft-js`. It checks 27 | whether the input string (first 2 cahracters only) is present in the `StringToTypeMap` 28 | mapping or not. If present, it converts the current block's type and called the `editor`'s 29 | `onChange` function. Otherwise, does nothing. By defualt, the above key-value mapping 30 | is passed. In custom implementation, users can pass their own mapping or extend 31 | the current one. 32 | */ 33 | const beforeInput = (editorState, inputString, onChange, mapping = StringToTypeMap) => { 34 | const selection = editorState.getSelection(); 35 | const block = getCurrentBlock(editorState); 36 | const blockType = block.getType(); 37 | if (blockType.indexOf(Block.ATOMIC) === 0) { 38 | return NOT_HANDLED; 39 | } 40 | const blockLength = block.getLength(); 41 | if (selection.getAnchorOffset() > 1 || blockLength > 1) { 42 | return NOT_HANDLED; 43 | } 44 | const blockTo = mapping[block.getText()[0] + inputString]; 45 | if (!blockTo) { 46 | return NOT_HANDLED; 47 | } 48 | const finalType = blockTo.split(':'); 49 | if (finalType.length < 1 || finalType.length > 3) { 50 | return NOT_HANDLED; 51 | } 52 | let fType = finalType[0]; 53 | if (finalType.length === 1) { 54 | if (blockType === finalType[0]) { 55 | return NOT_HANDLED; 56 | } 57 | } else if (finalType.length === 2) { 58 | if (blockType === finalType[1]) { 59 | return NOT_HANDLED; 60 | } 61 | if (blockType === finalType[0]) { 62 | fType = finalType[1]; 63 | } 64 | } else if (finalType.length === 3) { 65 | if (blockType === finalType[2]) { 66 | return NOT_HANDLED; 67 | } 68 | if (blockType === finalType[0]) { 69 | fType = finalType[1]; 70 | } else { 71 | fType = finalType[2]; 72 | } 73 | } 74 | onChange(resetBlockWithType(editorState, fType, { 75 | text: '', 76 | })); 77 | return HANDLED; 78 | }; 79 | 80 | 81 | export default beforeInput; 82 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/beforeinput.spec.js: -------------------------------------------------------------------------------- 1 | import createEditorState from '../model/content'; 2 | 3 | import { Block, /* HANDLED,*/ NOT_HANDLED } from './constants'; 4 | import beforeInput from './beforeinput'; 5 | 6 | describe('beforeInput()', () => { 7 | it('returns NOT_HANDLED for atomic like blocks', () => { 8 | const dummyData = { 9 | entityMap: {}, 10 | blocks: [{ 11 | key: 'etee', 12 | text: 'E', 13 | type: 'atomic', 14 | depth: 0, 15 | inlineStyleRanges: [], 16 | entityRanges: [ 17 | { 18 | offset: 0, 19 | length: 1, 20 | key: 3, 21 | }, 22 | ], 23 | data: {}, 24 | }], 25 | }; 26 | let es = createEditorState(dummyData); 27 | expect(beforeInput(es)).to.equal(NOT_HANDLED); 28 | dummyData.blocks[0].type = Block.IMAGE; 29 | es = createEditorState(dummyData); 30 | expect(beforeInput(es)).to.equal(NOT_HANDLED); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/blockStyleFn.js: -------------------------------------------------------------------------------- 1 | import { Block } from './constants'; 2 | 3 | /* 4 | Get custom classnames for each of the different block types supported. 5 | */ 6 | 7 | const BASE_BLOCK_CLASS = 'md-block'; 8 | 9 | export default (block) => { 10 | switch (block.getType()) { 11 | case Block.BLOCKQUOTE: 12 | return `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-quote md-RichEditor-blockquote`; 13 | case Block.UNSTYLED: 14 | return `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-paragraph`; 15 | case Block.ATOMIC: 16 | return `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-atomic`; 17 | case Block.CAPTION: 18 | return `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-caption`; 19 | case Block.TODO: { 20 | const data = block.getData(); 21 | const checkedClass = data.get('checked') === true ? 22 | `${BASE_BLOCK_CLASS}-todo-checked` : `${BASE_BLOCK_CLASS}-todo-unchecked`; 23 | let finalClass = `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-paragraph `; 24 | finalClass += `${BASE_BLOCK_CLASS}-todo ${checkedClass}`; 25 | return finalClass; 26 | } 27 | case Block.IMAGE: 28 | return `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-image`; 29 | case Block.BLOCKQUOTE_CAPTION: { 30 | const cls = `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-quote`; 31 | return `${cls} md-RichEditor-blockquote ${BASE_BLOCK_CLASS}-quote-caption`; 32 | } 33 | case Block.CODE: 34 | return `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-code-block`; 35 | default: return BASE_BLOCK_CLASS; 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/blockStyleFn.spec.js: -------------------------------------------------------------------------------- 1 | import { Map } from 'immutable'; 2 | import { ContentBlock } from 'draft-js'; 3 | import blockStyleFn from './blockStyleFn'; 4 | import { Block } from './constants'; 5 | 6 | const BASE_BLOCK_CLASS = 'md-block'; 7 | 8 | describe('blockStyleFn()', () => { 9 | it('should return block class for UNKNOWN', () => { 10 | const normalBlock = new ContentBlock({ 11 | type: 'some-unknown-type', 12 | }); 13 | expect(blockStyleFn(normalBlock)).to.equal(BASE_BLOCK_CLASS); 14 | }); 15 | 16 | it('should return block class for UNSTYLED', () => { 17 | const normalBlock = new ContentBlock({ 18 | type: Block.UNSTYLED, 19 | }); 20 | expect(blockStyleFn(normalBlock)).to.equal(`${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-paragraph`); 21 | }); 22 | 23 | it('should return block class for CAPTION', () => { 24 | const normalBlock = new ContentBlock({ 25 | type: Block.CAPTION, 26 | }); 27 | expect(blockStyleFn(normalBlock)).to.equal(`${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-caption`); 28 | }); 29 | 30 | it('should return block class for BLOCKQUOTE_CAPTION', () => { 31 | const normalBlock = new ContentBlock({ 32 | type: Block.BLOCKQUOTE_CAPTION, 33 | }); 34 | const cls = `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-quote`; 35 | expect(blockStyleFn(normalBlock)).to.equal( 36 | `${cls} md-RichEditor-blockquote ${BASE_BLOCK_CLASS}-quote-caption`); 37 | }); 38 | 39 | it('should return block class for BLOCKQUOTE', () => { 40 | const normalBlock = new ContentBlock({ 41 | type: Block.BLOCKQUOTE, 42 | }); 43 | expect(blockStyleFn(normalBlock)).to.equal( 44 | `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-quote md-RichEditor-blockquote`); 45 | }); 46 | 47 | it('should return block class for ATOMIC', () => { 48 | const normalBlock = new ContentBlock({ 49 | type: Block.ATOMIC, 50 | }); 51 | expect(blockStyleFn(normalBlock)).to.equal( 52 | `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-atomic`); 53 | }); 54 | 55 | it('should return block class for IMAGE', () => { 56 | const normalBlock = new ContentBlock({ 57 | type: Block.IMAGE, 58 | }); 59 | expect(blockStyleFn(normalBlock)).to.equal( 60 | `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-image`); 61 | }); 62 | 63 | it('should return block class for TODO', () => { 64 | const todoBlock = new ContentBlock({ 65 | type: Block.TODO, 66 | }); 67 | const todoBlockChecked = new ContentBlock({ 68 | type: Block.TODO, 69 | data: Map({ 70 | checked: true, 71 | }), 72 | }); 73 | 74 | const baseTodoClass = `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-paragraph`; 75 | 76 | expect(blockStyleFn(todoBlock)).to.equal( 77 | `${baseTodoClass} ${BASE_BLOCK_CLASS}-todo ${BASE_BLOCK_CLASS}-todo-unchecked`); 78 | expect(blockStyleFn(todoBlockChecked)).to.equal( 79 | `${baseTodoClass} ${BASE_BLOCK_CLASS}-todo ${BASE_BLOCK_CLASS}-todo-checked`); 80 | }); 81 | 82 | it('should return block class for CODE', () => { 83 | const normalBlock = new ContentBlock({ 84 | type: Block.CODE, 85 | }); 86 | expect(blockStyleFn(normalBlock)).to.equal( 87 | `${BASE_BLOCK_CLASS} ${BASE_BLOCK_CLASS}-code-block`); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/constants.js: -------------------------------------------------------------------------------- 1 | /* 2 | Some of the constants which are used throughout this project instead of 3 | directly using string. 4 | */ 5 | 6 | export const Block = { 7 | UNSTYLED: 'unstyled', 8 | PARAGRAPH: 'unstyled', 9 | OL: 'ordered-list-item', 10 | UL: 'unordered-list-item', 11 | H1: 'header-one', 12 | H2: 'header-two', 13 | H3: 'header-three', 14 | H4: 'header-four', 15 | H5: 'header-five', 16 | H6: 'header-six', 17 | CODE: 'code-block', 18 | BLOCKQUOTE: 'blockquote', 19 | PULLQUOTE: 'pullquote', 20 | ATOMIC: 'atomic', 21 | BLOCKQUOTE_CAPTION: 'block-quote-caption', 22 | CAPTION: 'caption', 23 | TODO: 'todo', 24 | IMAGE: 'atomic:image', 25 | BREAK: 'atomic:break', 26 | }; 27 | 28 | export const Inline = { 29 | BOLD: 'BOLD', 30 | CODE: 'CODE', 31 | ITALIC: 'ITALIC', 32 | STRIKETHROUGH: 'STRIKETHROUGH', 33 | UNDERLINE: 'UNDERLINE', 34 | HIGHLIGHT: 'HIGHLIGHT', 35 | }; 36 | 37 | export const Entity = { 38 | LINK: 'LINK', 39 | }; 40 | 41 | export const HYPERLINK = 'hyperlink'; 42 | export const HANDLED = 'handled'; 43 | export const NOT_HANDLED = 'not_handled'; 44 | 45 | export const KEY_COMMANDS = { 46 | addNewBlock: () => 'add-new-block', 47 | changeType: (type = '') => `changetype:${type}`, 48 | showLinkInput: () => 'showlinkinput', 49 | unlink: () => 'unlink', 50 | toggleInline: (type = '') => `toggleinline:${type}`, 51 | deleteBlock: () => 'delete-block', 52 | }; 53 | 54 | export default { 55 | Block, 56 | Inline, 57 | Entity, 58 | }; 59 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/constants.spec.js: -------------------------------------------------------------------------------- 1 | import { KEY_COMMANDS, Block, Inline } from './constants'; 2 | 3 | describe('constants', () => { 4 | it('changeType should return appended with block type', () => { 5 | expect(KEY_COMMANDS.changeType()).to.equal('changetype:'); 6 | expect(KEY_COMMANDS.changeType('')).to.equal('changetype:'); 7 | expect(KEY_COMMANDS.changeType(Block.ATOMIC)).to.equal(`changetype:${Block.ATOMIC}`); 8 | expect(KEY_COMMANDS.changeType(Block.IMAGE)).to.equal(`changetype:${Block.IMAGE}`); 9 | }); 10 | 11 | it('toggleInline should return appended with inline type', () => { 12 | expect(KEY_COMMANDS.toggleInline()).to.equal('toggleinline:'); 13 | expect(KEY_COMMANDS.toggleInline('')).to.equal('toggleinline:'); 14 | expect(KEY_COMMANDS.toggleInline(Inline.BOLD)).to.equal(`toggleinline:${Inline.BOLD}`); 15 | expect(KEY_COMMANDS.toggleInline(Inline.ITALIC)).to.equal(`toggleinline:${Inline.ITALIC}`); 16 | }); 17 | 18 | it('showLinkInput', () => { 19 | expect(KEY_COMMANDS.showLinkInput()).to.equal('showlinkinput'); 20 | }); 21 | 22 | it('addNewBlock', () => { 23 | expect(KEY_COMMANDS.addNewBlock()).to.equal('add-new-block'); 24 | }); 25 | 26 | it('deleteBlock', () => { 27 | expect(KEY_COMMANDS.deleteBlock()).to.equal('delete-block'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/customstylemap.js: -------------------------------------------------------------------------------- 1 | import { Inline } from './constants'; 2 | 3 | /* 4 | Custom style map for custom entities like Hihglight. 5 | */ 6 | const customStyleMap = { 7 | [Inline.HIGHLIGHT]: { 8 | backgroundColor: 'yellow', 9 | }, 10 | [Inline.CODE]: { 11 | fontFamily: 'Consolas, "Liberation Mono", Menlo, Courier, monospace', 12 | margin: '4px 0', 13 | fontSize: '0.9em', 14 | padding: '1px 3px', 15 | color: '#555', 16 | backgroundColor: '#fcfcfc', 17 | border: '1px solid #ccc', 18 | borderBottomColor: '#bbb', 19 | borderRadius: 3, 20 | boxShadow: 'inset 0 -1px 0 #bbb', 21 | }, 22 | }; 23 | 24 | export default customStyleMap; 25 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Returns the `boundingClientRect` of the passed selection. 3 | */ 4 | export const getSelectionRect = (selected) => { 5 | const _rect = selected.getRangeAt(0).getBoundingClientRect(); 6 | // selected.getRangeAt(0).getBoundingClientRect() 7 | let rect = _rect && _rect.top ? _rect : selected.getRangeAt(0).getClientRects()[0]; 8 | if (!rect) { 9 | if (selected.anchorNode && selected.anchorNode.getBoundingClientRect) { 10 | rect = selected.anchorNode.getBoundingClientRect(); 11 | rect.isEmptyline = true; 12 | } else { 13 | return null; 14 | } 15 | } 16 | return rect; 17 | }; 18 | 19 | /* 20 | Returns the native selection node. 21 | */ 22 | export const getSelection = (root) => { 23 | let t = null; 24 | if (root.getSelection) { 25 | t = root.getSelection(); 26 | } else if (root.document.getSelection) { 27 | t = root.document.getSelection(); 28 | } else if (root.document.selection) { 29 | t = root.document.selection.createRange().text; 30 | } 31 | return t; 32 | }; 33 | 34 | /* 35 | Recursively finds the DOM Element of the block where the cursor is currently present. 36 | If not found, returns null. 37 | */ 38 | export const getSelectedBlockNode = (root) => { 39 | const selection = root.getSelection(); 40 | if (selection.rangeCount === 0) { 41 | return null; 42 | } 43 | let node = selection.getRangeAt(0).startContainer; 44 | // console.log(node); 45 | do { 46 | if (node.getAttribute && node.getAttribute('data-block') === 'true') { 47 | return node; 48 | } 49 | node = node.parentNode; 50 | // console.log(node); 51 | } while (node !== null); 52 | return null; 53 | }; 54 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/keybinding.js: -------------------------------------------------------------------------------- 1 | import { getDefaultKeyBinding, KeyBindingUtil } from 'draft-js'; 2 | 3 | import { KEY_COMMANDS } from './constants'; 4 | 5 | const { changeType, showLinkInput, unlink } = KEY_COMMANDS; 6 | 7 | /* 8 | Emits various key commands to be used by `handleKeyCommand` in `Editor` based 9 | on various key combos. 10 | */ 11 | export default (e) => { 12 | if (KeyBindingUtil.hasCommandModifier(e) && e.which === 75) { 13 | if (e.shiftKey) { 14 | return unlink(); 15 | } 16 | return showLinkInput(); 17 | } 18 | if (e.altKey === true && !e.ctrlKey) { 19 | if (e.shiftKey === true) { 20 | switch (e.which) { 21 | // Alt + Shift + A 22 | // case 65: return addNewBlock(); 23 | default: return getDefaultKeyBinding(e); 24 | } 25 | } 26 | switch (e.which) { 27 | // 1 28 | case 49: return changeType('ordered-list-item'); 29 | // @ 30 | case 50: return showLinkInput(); 31 | // # 32 | case 51: return changeType('header-three'); 33 | // * 34 | case 56: return changeType('unordered-list-item'); 35 | // < 36 | case 188: return changeType('caption'); 37 | // // - 38 | // case 189: return 'changetype:caption'; 39 | // > 40 | case 190: return changeType('unstyled'); 41 | // " 42 | case 222: return changeType('blockquote'); 43 | default: return getDefaultKeyBinding(e); 44 | } 45 | } 46 | // if (e.keyCode === 46 && !e.ctrlKey) { 47 | // return KEY_COMMANDS.deleteBlock(); 48 | // } 49 | return getDefaultKeyBinding(e); 50 | }; 51 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/rendermap.js: -------------------------------------------------------------------------------- 1 | import { Map } from 'immutable'; 2 | import { DefaultDraftBlockRenderMap } from 'draft-js'; 3 | 4 | import { Block } from './constants'; 5 | 6 | /* 7 | Mapping that returns containers for the various block types. 8 | */ 9 | const RenderMap = Map({ 10 | [Block.CAPTION]: { 11 | element: 'cite', 12 | }, 13 | [Block.BLOCKQUOTE_CAPTION]: { 14 | element: 'blockquote', 15 | }, 16 | [Block.TODO]: { 17 | element: 'div', 18 | }, 19 | [Block.IMAGE]: { 20 | element: 'figure', 21 | }, 22 | [Block.BREAK]: { 23 | element: 'div', 24 | }, 25 | }).merge(DefaultDraftBlockRenderMap); 26 | 27 | 28 | export default RenderMap; 29 | -------------------------------------------------------------------------------- /frame/src/components/vendor/util/rendermap.spec.js: -------------------------------------------------------------------------------- 1 | import renderMap from './rendermap'; 2 | import { Block } from './constants'; 3 | 4 | describe('rendermap', () => { 5 | it('returns cite for CAPTION', () => { 6 | expect(renderMap.get(Block.CAPTION)).to.deep.equal({ 7 | element: 'cite', 8 | }); 9 | }); 10 | 11 | it('returns blockquote for BLOCKQUOTE_CAPTION', () => { 12 | expect(renderMap.get(Block.BLOCKQUOTE_CAPTION)).to.deep.equal({ 13 | element: 'blockquote', 14 | }); 15 | }); 16 | 17 | it('returns div for TODO', () => { 18 | expect(renderMap.get(Block.TODO)).to.deep.equal({ 19 | element: 'div', 20 | }); 21 | }); 22 | 23 | it('returns figure for IMAGE', () => { 24 | expect(renderMap.get(Block.IMAGE)).to.deep.equal({ 25 | element: 'figure', 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /frame/src/data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "savedSettings": { 3 | "online": false, 4 | "NLPServer": "http://localhost:80/", 5 | "activeTheme": "ocean", 6 | "loadedThemes": [ 7 | "light", 8 | "dark", 9 | "clean", 10 | "black", 11 | "ocean", 12 | "dim", 13 | "neon", 14 | "night", 15 | "paper", 16 | "present" 17 | ], 18 | "librariesPath": "src/data/libraries_collections", 19 | "defaultLibrary": "default" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frame/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App/App' 4 | 5 | import './assets/css/all.css'; 6 | import './assets/js/all'; 7 | // import registerServiceWorker from "./registerServiceWorker"; 8 | 9 | // Create root element in DOM 10 | const root = document.createElement('div'); 11 | root.id = "app"; 12 | document.body.appendChild( root ); 13 | document.title = "Frame - notebook that insights"; 14 | 15 | const appEl = document.getElementById('app'); 16 | 17 | function render() { 18 | ReactDOM.render( 19 | , 20 | appEl 21 | ); 22 | }; 23 | 24 | render(); 25 | 26 | // registerServiceWorker(); -------------------------------------------------------------------------------- /frame/src/lib/custom-vendor/tree-node-renderer.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Children, cloneElement } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import styles from './tree-node-renderer.scss'; 4 | 5 | class MinimalThemeTreeNodeRenderer extends Component { 6 | constructor (props) { 7 | super(props) 8 | 9 | this.state = {} 10 | this.bound = { 11 | handleMouseOver: this.handleMouseOver.bind(this), 12 | handleMouseLeave: this.handleMouseLeave.bind(this) 13 | } 14 | } 15 | 16 | handleMouseOver () { 17 | if (!this.state.highlight) { 18 | this.setState({highlight: true}) 19 | } 20 | } 21 | 22 | handleMouseLeave () { 23 | this.setState({highlight: false}) 24 | } 25 | 26 | render() { 27 | const { 28 | children, 29 | swapFrom, 30 | swapLength, 31 | swapDepth, 32 | scaffoldBlockPxWidth, 33 | lowerSiblingCounts, 34 | connectDropTarget, 35 | isOver, 36 | draggedNode, 37 | canDrop, 38 | treeIndex, 39 | treeId, 40 | listIndex, 41 | rowDirection, 42 | getPrevRow, // Delete from otherProps 43 | node, // Delete from otherProps 44 | path, // Delete from otherProps 45 | ...otherProps 46 | } = this.props; 47 | // Construct the scaffold representing the structure of the tree 48 | const scaffoldBlockCount = lowerSiblingCounts.length - 1; 49 | let dropType 50 | if (canDrop && !isOver) { 51 | dropType = 'validDrop' 52 | } else if (!canDrop && isOver) { 53 | dropType = 'invalidDrop' 54 | } 55 | 56 | return connectDropTarget( 57 |
{} } className={styles.node + (this.state.highlight ? ` ${styles.highlight}` : '') + (dropType ? ` ${styles[dropType]}` : '')}> 58 |
62 | {Children.map(children, child => 63 | cloneElement(child, { 64 | isOver, 65 | canDrop, 66 | draggedNode, 67 | }) 68 | )} 69 |
70 |
71 | ); 72 | } 73 | } 74 | MinimalThemeTreeNodeRenderer.defaultProps = { 75 | swapFrom: null, 76 | swapDepth: null, 77 | swapLength: null, 78 | canDrop: false, 79 | draggedNode: null, 80 | rowDirection: 'ltr' 81 | }; 82 | 83 | MinimalThemeTreeNodeRenderer.propTypes = { 84 | treeIndex: PropTypes.number.isRequired, 85 | swapFrom: PropTypes.number, 86 | swapDepth: PropTypes.number, 87 | swapLength: PropTypes.number, 88 | scaffoldBlockPxWidth: PropTypes.number.isRequired, 89 | lowerSiblingCounts: PropTypes.arrayOf(PropTypes.number).isRequired, 90 | treeId: PropTypes.string.isRequired, 91 | listIndex: PropTypes.number.isRequired, 92 | rowDirection: PropTypes.string, 93 | children: PropTypes.node.isRequired, 94 | 95 | // Drop target 96 | connectDropTarget: PropTypes.func.isRequired, 97 | isOver: PropTypes.bool.isRequired, 98 | canDrop: PropTypes.bool, 99 | draggedNode: PropTypes.shape({}), 100 | 101 | // used in dndManager 102 | getPrevRow: PropTypes.func.isRequired, 103 | node: PropTypes.shape({}).isRequired, 104 | path: PropTypes.arrayOf( 105 | PropTypes.oneOfType([PropTypes.string, PropTypes.number]) 106 | ).isRequired 107 | }; 108 | 109 | export default MinimalThemeTreeNodeRenderer; 110 | -------------------------------------------------------------------------------- /frame/src/lib/custom-vendor/tree-node-renderer.scss: -------------------------------------------------------------------------------- 1 | .node { 2 | width: 50%; 3 | white-space: nowrap; 4 | position: relative; 5 | text-align: left; 6 | min-width: 100%; 7 | overflow: hidden; 8 | } 9 | 10 | .nodeContent { 11 | position: absolute; 12 | top: 0; 13 | bottom: 0; 14 | width: 80%; 15 | } 16 | 17 | .validDrop { 18 | background: #26C281; 19 | } 20 | 21 | .invalidDrop { 22 | background: #C0392B; 23 | } 24 | 25 | .highlight { 26 | background: rgba(240, 240, 240, 0.7); 27 | height: 100%; 28 | cursor: pointer; 29 | } -------------------------------------------------------------------------------- /frame/src/utils/create-db.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars: 0 */ 2 | 3 | import localforage from 'localforage'; 4 | 5 | 6 | export default function openDB(key) { 7 | const store = localforage.createInstance({name: "default"}); 8 | return store; 9 | } -------------------------------------------------------------------------------- /frame/src/utils/generate-uuid.js: -------------------------------------------------------------------------------- 1 | // https://gist.github.com/jed/982883 2 | export default function generateUUID() { 3 | return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => 4 | (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) // eslint-disable-line no-bitwise 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /frame/src/utils/get-timestamp.js: -------------------------------------------------------------------------------- 1 | export default function getTimestamp(date, locale) { 2 | const event = (date===undefined) ? new Date() : new Date(date); 3 | return `${event.toLocaleDateString(locale)} ${event.toLocaleTimeString(locale)}` 4 | }; -------------------------------------------------------------------------------- /frame/src/utils/load-db.js: -------------------------------------------------------------------------------- 1 | /* eslint prefer-arrow-callback: 0 */ 2 | /* eslint func-names: 0 */ 3 | /* eslint no-unused-vars: 0 */ 4 | /* eslint no-var: 0 */ 5 | /* eslint no-console: 0 */ 6 | /* eslint consistent-return: 0 */ 7 | /* eslint no-alert: 0 */ 8 | 9 | import localforage from "localforage"; 10 | 11 | // Load from LocalForage (default offline storage option) 12 | export default function getFromDB (key) { 13 | localforage.getItem(key, function(err, value) { 14 | if (err) { 15 | console.error(err); 16 | alert(err); 17 | return null; 18 | } 19 | // console.log("Getting item from ", key, value); 20 | return value; 21 | }); 22 | } -------------------------------------------------------------------------------- /frame/src/utils/replace-entry.js: -------------------------------------------------------------------------------- 1 | /* eslint prefer-arrow-callback: 0 */ 2 | /* eslint func-names: 0 */ 3 | /* eslint no-unused-vars: 0 */ 4 | /* eslint no-var: 0 */ 5 | /* eslint no-console: 0 */ 6 | /* eslint no-plusplus: 0 */ 7 | /* eslint no-empty: 0 */ 8 | 9 | export default function replaceEntry(entry, Entries) { 10 | const newEntries = Entries; 11 | for (let i=0; i").join("\r\r\n\n"); 28 | const reg = /(<([^>]+)>)/ig; 29 | stripped = stripped.replace(reg, "") 30 | stripped = stripped.replace(/[^\x00-\x7F]/g, ""); 31 | stripped = stripped.replace(/'/g,"'"); 32 | stripped = stripped.replace("&'", "'"); 33 | stripped = stripped.replace(/"/g, '"'); 34 | return stripped; 35 | } -------------------------------------------------------------------------------- /frame/src/utils/vendor/classnames.js: -------------------------------------------------------------------------------- 1 | // very simple className utility for creating a classname string... 2 | // Falsy arguments are ignored: 3 | // 4 | // const active = true 5 | // const className = classnames( 6 | // "class1", 7 | // !active && "class2", 8 | // active && "class3" 9 | // ); // returns -> class1 class3"; 10 | // 11 | export default function classnames(...classes) { 12 | // Use Boolean constructor as a filter callback 13 | // Allows for loose type truthy/falsey checks 14 | // Boolean("") === false; 15 | // Boolean(false) === false; 16 | // Boolean(undefined) === false; 17 | // Boolean(null) === false; 18 | // Boolean(0) === false; 19 | // Boolean("classname") === true; 20 | return classes.filter(Boolean).join(' '); 21 | } 22 | -------------------------------------------------------------------------------- /frame/src/utils/vendor/default-handlers.js: -------------------------------------------------------------------------------- 1 | export function defaultGetNodeKey({ treeIndex }) { 2 | return treeIndex; 3 | } 4 | 5 | // Cheap hack to get the text of a react object 6 | function getReactElementText(parent) { 7 | if (typeof parent === 'string') { 8 | return parent; 9 | } 10 | 11 | if ( 12 | typeof parent !== 'object' || 13 | !parent.props || 14 | !parent.props.children || 15 | (typeof parent.props.children !== 'string' && 16 | typeof parent.props.children !== 'object') 17 | ) { 18 | return ''; 19 | } 20 | 21 | if (typeof parent.props.children === 'string') { 22 | return parent.props.children; 23 | } 24 | 25 | return parent.props.children 26 | .map(child => getReactElementText(child)) 27 | .join(''); 28 | } 29 | 30 | // Search for a query string inside a node property 31 | function stringSearch(key, searchQuery, node, path, treeIndex) { 32 | if (typeof node[key] === 'function') { 33 | // Search within text after calling its function to generate the text 34 | return ( 35 | String(node[key]({ node, path, treeIndex })).indexOf(searchQuery) > -1 36 | ); 37 | } 38 | if (typeof node[key] === 'object') { 39 | // Search within text inside react elements 40 | return getReactElementText(node[key]).indexOf(searchQuery) > -1; 41 | } 42 | 43 | // Search within string 44 | return node[key] && String(node[key]).indexOf(searchQuery) > -1; 45 | } 46 | 47 | export function defaultSearchMethod({ node, path, treeIndex, searchQuery }) { 48 | return ( 49 | stringSearch('title', searchQuery, node, path, treeIndex) || 50 | stringSearch('subtitle', searchQuery, node, path, treeIndex) 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /frame/src/utils/vendor/generic-utils.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | 3 | export function slideRows(rows, fromIndex, toIndex, count = 1) { 4 | const rowsWithoutMoved = [ 5 | ...rows.slice(0, fromIndex), 6 | ...rows.slice(fromIndex + count), 7 | ]; 8 | 9 | return [ 10 | ...rowsWithoutMoved.slice(0, toIndex), 11 | ...rows.slice(fromIndex, fromIndex + count), 12 | ...rowsWithoutMoved.slice(toIndex), 13 | ]; 14 | } 15 | -------------------------------------------------------------------------------- /frame/src/utils/vendor/generic-utils.test.js: -------------------------------------------------------------------------------- 1 | import { slideRows } from './generic-utils'; 2 | 3 | describe('slideRows', () => { 4 | it('should handle empty slide', () => { 5 | expect(slideRows([0, 1, 2], 1, 2, 0)).toEqual([0, 1, 2]); 6 | expect(slideRows([0, 1, 2], 1, 0, 0)).toEqual([0, 1, 2]); 7 | expect(slideRows([0, 1, 2], 1, 1, 0)).toEqual([0, 1, 2]); 8 | }); 9 | 10 | it('should handle single slides', () => { 11 | expect(slideRows([0, 1, 2], 1, 1, 1)).toEqual([0, 1, 2]); 12 | expect(slideRows([0, 1, 2], 1, 2, 1)).toEqual([0, 2, 1]); 13 | expect(slideRows([0, 1, 2], 1, 0, 1)).toEqual([1, 0, 2]); 14 | expect(slideRows([0, 1, 2], 0, 2, 1)).toEqual([1, 2, 0]); 15 | }); 16 | 17 | it('should handle multi slides', () => { 18 | expect(slideRows([0, 1, 2], 1, 0, 2)).toEqual([1, 2, 0]); 19 | expect(slideRows([0, 1, 2, 3], 0, 2, 2)).toEqual([2, 3, 0, 1]); 20 | expect(slideRows([0, 1, 2, 3], 3, 0, 2)).toEqual([3, 0, 1, 2]); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frame/src/utils/vendor/memoized-tree-data-utils.js: -------------------------------------------------------------------------------- 1 | import { 2 | insertNode, 3 | getDescendantCount, 4 | getFlatDataFromTree, 5 | } from './tree-data-utils'; 6 | 7 | const memoize = f => { 8 | let savedArgsArray = []; 9 | let savedKeysArray = []; 10 | let savedResult = null; 11 | 12 | return args => { 13 | const keysArray = Object.keys(args).sort(); 14 | const argsArray = keysArray.map(key => args[key]); 15 | 16 | // If the arguments for the last insert operation are different than this time, 17 | // recalculate the result 18 | if ( 19 | argsArray.length !== savedArgsArray.length || 20 | argsArray.some((arg, index) => arg !== savedArgsArray[index]) || 21 | keysArray.some((key, index) => key !== savedKeysArray[index]) 22 | ) { 23 | savedArgsArray = argsArray; 24 | savedKeysArray = keysArray; 25 | savedResult = f(args); 26 | } 27 | 28 | return savedResult; 29 | }; 30 | }; 31 | 32 | export const memoizedInsertNode = memoize(insertNode); 33 | export const memoizedGetFlatDataFromTree = memoize(getFlatDataFromTree); 34 | export const memoizedGetDescendantCount = memoize(getDescendantCount); 35 | -------------------------------------------------------------------------------- /frame/src/utils/vendor/memoized-tree-data-utils.test.js: -------------------------------------------------------------------------------- 1 | import { insertNode } from './tree-data-utils'; 2 | 3 | import { memoizedInsertNode } from './memoized-tree-data-utils'; 4 | 5 | describe('insertNode', () => { 6 | it('should handle empty data', () => { 7 | const params = { 8 | treeData: [], 9 | depth: 0, 10 | minimumTreeIndex: 0, 11 | newNode: {}, 12 | getNodeKey: ({ treeIndex }) => treeIndex, 13 | }; 14 | 15 | let firstCall = insertNode(params); 16 | let secondCall = insertNode(params); 17 | expect(firstCall === secondCall).toEqual(false); 18 | 19 | firstCall = memoizedInsertNode(params); 20 | secondCall = memoizedInsertNode(params); 21 | expect(firstCall === secondCall).toEqual(true); 22 | 23 | expect( 24 | memoizedInsertNode(params) === 25 | memoizedInsertNode({ ...params, treeData: [{}] }) 26 | ).toEqual(false); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /frame/webpack.common.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const webpack = require("webpack"); 5 | 6 | module.exports = { 7 | entry:["babel-polyfill", path.resolve(__dirname, 'src/index.js')], 8 | resolve: {extensions: ['.js', '.jsx', '.tsx', '.ts']}, 9 | node: { 10 | fs: "empty" 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.jsx?$/, 16 | exclude: /(node_modules|bower_components)/, 17 | use: { 18 | loader: "babel-loader", 19 | options: { 20 | cacheDirectory: true, 21 | plugins: [ 22 | // Here, we include babel plugins that are only required for the 23 | // renderer process. The 'transform-*' plugins must be included 24 | // before react-hot-loader/babel 25 | 'transform-class-properties', 26 | 'transform-es2015-classes', 27 | 'react-hot-loader/babel' 28 | ] 29 | } 30 | } 31 | }, 32 | { 33 | test: /\.tsx?$/, 34 | use: 'ts-loader', 35 | exclude: /node_modules/ 36 | }, 37 | { 38 | test: /\.scss$/, 39 | loader: "style-loader!css-loader" 40 | }, 41 | { 42 | test: /\.css$/, 43 | loader: "style-loader!css-loader" 44 | }, 45 | 46 | { 47 | test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/, 48 | loader: "url-loader", 49 | options: { 50 | limit: 10000 51 | } 52 | }, 53 | { 54 | test: /vendor\/.+\.(jsx|js)$/, 55 | loader: "imports?jQuery=jquery,$=jquery,this=>window" 56 | } 57 | ] 58 | }, 59 | plugins: [ new HtmlWebpackPlugin() ], 60 | stats: { 61 | warnings: false 62 | } 63 | }; -------------------------------------------------------------------------------- /frame/webpack.config.eslint.js: -------------------------------------------------------------------------------- 1 | require('babel-register'); 2 | 3 | module.exports = require('./webpack.dev'); 4 | -------------------------------------------------------------------------------- /frame/webpack.dev.electron.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const { spawn } = require('child_process'); 5 | 6 | // Config directories 7 | const SRC_DIR = path.resolve(__dirname, 'src'); 8 | const OUTPUT_DIR = path.resolve(__dirname, 'electron/dev/dist'); 9 | 10 | // Any directories you will be adding code/files into, need to be added to this array so webpack will pick them up 11 | const defaultInclude = [SRC_DIR]; 12 | module.exports = { 13 | mode: 'development', 14 | entry: ['babel-polyfill', path.resolve(__dirname, 'src/index.js')], 15 | resolve: {extensions: [".js", ".jsx", ".tsx", ".ts"]}, 16 | output: { 17 | path: OUTPUT_DIR, 18 | publicPath: '/', 19 | filename: 'bundle-electron-dev.js' 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /\.jsx?$/, 25 | exclude: /(node_modules|bower_components)/, 26 | use: { 27 | loader: "babel-loader", 28 | options: { 29 | cacheDirectory: true, 30 | plugins: [ 31 | // Here, we include babel plugins that are only required for the 32 | // renderer process. The 'transform-*' plugins must be included 33 | // before react-hot-loader/babel 34 | 'transform-class-properties', 35 | 'transform-es2015-classes', 36 | 'react-hot-loader/babel' 37 | ] 38 | } 39 | } 40 | }, 41 | { 42 | test: /\.tsx?$/, 43 | use: 'ts-loader', 44 | exclude: /node_modules/ 45 | }, 46 | { 47 | test: /\.scss$/, 48 | loader: "style-loader!css-loader" 49 | }, 50 | { 51 | test: /\.css$/, 52 | loader: "style-loader!css-loader" 53 | }, 54 | 55 | { 56 | test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/, 57 | loader: "url-loader", 58 | options: { 59 | limit: 10000 60 | } 61 | }, 62 | { 63 | test: /vendor\/.+\.(jsx|js)$/, 64 | loader: "imports?jQuery=jquery,$=jquery,this=>window" 65 | } 66 | ] 67 | }, 68 | target: 'electron-renderer', 69 | plugins: [ 70 | new HtmlWebpackPlugin(), 71 | new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('development')}) 72 | ], 73 | devtool: 'cheap-source-map', 74 | devServer: { 75 | contentBase: OUTPUT_DIR, 76 | stats: { 77 | colors: true, 78 | chunks: false, 79 | children: false 80 | }, 81 | setup() { 82 | spawn( 83 | 'electron', 84 | ['.'], 85 | { shell: true, env: process.env, stdio: 'inherit' } 86 | ) 87 | .on('close', code => process.exit(0)) 88 | .on('error', spawnError => console.ernror(spawnError)); 89 | } 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /frame/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | const webpack = require("webpack"); 4 | const path = require('path'); 5 | const FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin"); 6 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 7 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 8 | const DashboardPlugin = require('webpack-dashboard/plugin'); 9 | 10 | module.exports = merge(common, 11 | { 12 | mode: 'development', 13 | output: { path: path.resolve("./output/webpack/development"),filename: "bundle-web-dev.js"}, 14 | devtool: 'inline-source-map', 15 | devServer: { 16 | disableHostCheck: true, 17 | hot: true, 18 | historyApiFallback: true, 19 | contentBase: "./output/webpack/devserver", 20 | watchContentBase: true, 21 | port: 3001, 22 | overlay: { warnings: true,errors: true}, 23 | stats: { 24 | assets: false, 25 | colors: true, 26 | version: false, 27 | hash: false, 28 | timings: false, 29 | chunks: false, 30 | chunkModules: false, 31 | modules: true, 32 | errorDetails: true 33 | } 34 | }, 35 | plugins: [ 36 | new CleanWebpackPlugin(['./output/webpack/development']), 37 | new FriendlyErrorsWebpackPlugin(), 38 | new webpack.HotModuleReplacementPlugin(), 39 | //new webpack.NoEmitOnErrorsPlugin(), // Causes it to go to console instead of web page 40 | new webpack.DefinePlugin({"process.env.NODE_ENV": JSON.stringify("development")}), 41 | new webpack.LoaderOptionsPlugin({debug: true}), 42 | //new BundleAnalyzerPlugin(), 43 | new DashboardPlugin() 44 | ], 45 | module: { 46 | rules: [ 47 | { 48 | enforce: "pre", 49 | test: /\.js$/, 50 | exclude: /node_modules/, 51 | use: { 52 | loader: "eslint-loader", 53 | options: { 54 | formatter: require("eslint-friendly-formatter"), 55 | quiet: false, 56 | failOnError: true, 57 | failOnWarning: false, 58 | emitError: true, 59 | emitWarning: true, 60 | configFile: "./.eslintrc.json", 61 | outputReport: { 62 | filePath: 'checkstyle.xml', 63 | formatter: require('eslint/lib/formatters/checkstyle') 64 | } 65 | } 66 | }, 67 | } 68 | ] 69 | }, 70 | stats: { 71 | warnings: false 72 | } 73 | }); -------------------------------------------------------------------------------- /frame/webpack.prod.electron.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const BabiliPlugin = require('babili-webpack-plugin'); 5 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 6 | 7 | // Config directories 8 | const SRC_DIR = path.resolve(__dirname, 'src'); 9 | const OUTPUT_DIR = path.resolve(__dirname, 'electron/prod/dist'); 10 | 11 | // Any directories you will be adding code/files into, need to be added to this array so webpack will pick them up 12 | const defaultInclude = [SRC_DIR]; 13 | 14 | module.exports = { 15 | mode: 'production', 16 | entry: ['babel-polyfill', path.resolve(__dirname, 'src/index.js')], 17 | resolve: {extensions: [".js", ".jsx", ".tsx", ".ts"]}, 18 | output: { 19 | path: OUTPUT_DIR, 20 | publicPath: './', 21 | filename: 'bundle-electron-prod.js' 22 | }, 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.jsx?$/, 27 | exclude: /(node_modules|bower_components)/, 28 | use: { 29 | loader: "babel-loader", 30 | options: { 31 | cacheDirectory: true, 32 | plugins: [ 33 | // Here, we include babel plugins that are only required for the 34 | // renderer process. The 'transform-*' plugins must be included 35 | // before react-hot-loader/babel 36 | 'transform-class-properties', 37 | 'transform-es2015-classes', 38 | 'react-hot-loader/babel' 39 | ] 40 | } 41 | } 42 | }, 43 | { 44 | test: /\.tsx?$/, 45 | use: 'ts-loader', 46 | exclude: /node_modules/ 47 | }, 48 | { 49 | test: /\.scss$/, 50 | loader: "style-loader!css-loader" 51 | }, 52 | { 53 | test: /\.css$/, 54 | loader: "style-loader!css-loader" 55 | }, 56 | 57 | { 58 | test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/, 59 | loader: "url-loader", 60 | options: { 61 | limit: 10000 62 | } 63 | }, 64 | { 65 | test: /vendor\/.+\.(jsx|js)$/, 66 | loader: "imports?jQuery=jquery,$=jquery,this=>window" 67 | } 68 | ] 69 | }, 70 | target: 'electron-renderer', 71 | plugins: [ 72 | new HtmlWebpackPlugin(), 73 | new ExtractTextPlugin('bundle.css'), 74 | new webpack.DefinePlugin({ 75 | 'process.env.NODE_ENV': JSON.stringify('production') 76 | }), 77 | new BabiliPlugin() 78 | ], 79 | stats: { 80 | colors: true, 81 | children: false, 82 | chunks: false, 83 | modules: false 84 | } 85 | }; 86 | -------------------------------------------------------------------------------- /frame/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const webpack = require('webpack'); 3 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 4 | const common = require('./webpack.common.js'); 5 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 6 | const path = require('path'); 7 | 8 | module.exports = merge(common, { 9 | mode: 'production', 10 | output: { path: path.resolve("./output/webpack/production"),filename: "bundle-web-prod.js"}, 11 | plugins: [ 12 | new UglifyJSPlugin({ sourceMap: true }), 13 | new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')}), 14 | new CleanWebpackPlugin(['./output/webpack/production']), 15 | ], 16 | }); -------------------------------------------------------------------------------- /screenshots/frame_screenshot_01-21-2019_alice_in_wonderland_information_extraction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/screenshots/frame_screenshot_01-21-2019_alice_in_wonderland_information_extraction.png -------------------------------------------------------------------------------- /screenshots/frame_screenshot_01-21-2019_cryptocurrency_analysis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/screenshots/frame_screenshot_01-21-2019_cryptocurrency_analysis.png -------------------------------------------------------------------------------- /screenshots/frame_screenshot_01-21-2019_sicko_mode_visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/screenshots/frame_screenshot_01-21-2019_sicko_mode_visualization.png -------------------------------------------------------------------------------- /screenshots/frame_screenshot_01-21-2019_this_is_water_summarization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/screenshots/frame_screenshot_01-21-2019_this_is_water_summarization.png -------------------------------------------------------------------------------- /screenshots/framed_video_animation_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jddunn/frame/a002056b22d9986ec41d0a07dff3641c3582c6f4/screenshots/framed_video_animation_demo.gif --------------------------------------------------------------------------------