├── .github ├── contributing.md ├── dependabot.yml ├── issue_template.md └── workflows │ ├── appstore-build-publish.yml │ ├── dependabot-approve-merge.yml │ ├── lint-info-xml.yml │ ├── lint-php-cs.yml │ ├── lint-php.yml │ ├── node.yml │ ├── phpunit-mysql.yml │ ├── phpunit-oci.yml │ ├── phpunit-pgsql.yml │ └── phpunit-sqlite.yml ├── .gitignore ├── .nextcloudignore ├── .php-cs-fixer.dist.php ├── .scrutinizer.yml ├── .tx └── config ├── CHANGELOG.md ├── Makefile ├── README.md ├── appinfo ├── info.xml └── routes.php ├── babel.config.js ├── composer.json ├── composer.lock ├── css ├── DroidSansMono │ ├── DroidSansMono-webfont.eot │ ├── DroidSansMono-webfont.svg │ ├── DroidSansMono-webfont.ttf │ ├── DroidSansMono-webfont.woff │ ├── Google Android License.txt │ ├── stylesheet.css │ ├── stylesheet.css.map │ └── stylesheet.scss ├── merged.css ├── merged.css.map ├── merged.scss ├── mobile.css ├── mobile.css.map ├── mobile.scss ├── public-share.css ├── public-share.css.map ├── public-share.scss ├── style.css ├── style.css.map └── style.scss ├── img ├── app.png ├── app.svg ├── image.svg ├── mixed.svg └── text.svg ├── js ├── ImportAce.js ├── SyntaxMode.js ├── editor.js ├── index.js ├── newfileplugin.js ├── public-share.js ├── sidebarpreview.js └── supported_mimetypes.json ├── krankerl.toml ├── l10n ├── .gitkeep ├── af.js ├── af.json ├── ar.js ├── ar.json ├── ast.js ├── ast.json ├── az.js ├── az.json ├── bg.js ├── bg.json ├── bn_BD.js ├── bn_BD.json ├── br.js ├── br.json ├── bs.js ├── bs.json ├── ca.js ├── ca.json ├── cs.js ├── cs.json ├── cy_GB.js ├── cy_GB.json ├── da.js ├── da.json ├── de.js ├── de.json ├── de_DE.js ├── de_DE.json ├── el.js ├── el.json ├── en_GB.js ├── en_GB.json ├── eo.js ├── eo.json ├── es.js ├── es.json ├── es_419.js ├── es_419.json ├── es_AR.js ├── es_AR.json ├── es_CL.js ├── es_CL.json ├── es_CO.js ├── es_CO.json ├── es_CR.js ├── es_CR.json ├── es_DO.js ├── es_DO.json ├── es_EC.js ├── es_EC.json ├── es_GT.js ├── es_GT.json ├── es_HN.js ├── es_HN.json ├── es_MX.js ├── es_MX.json ├── es_NI.js ├── es_NI.json ├── es_PA.js ├── es_PA.json ├── es_PE.js ├── es_PE.json ├── es_PR.js ├── es_PR.json ├── es_PY.js ├── es_PY.json ├── es_SV.js ├── es_SV.json ├── es_UY.js ├── es_UY.json ├── et_EE.js ├── et_EE.json ├── eu.js ├── eu.json ├── fa.js ├── fa.json ├── fi.js ├── fi.json ├── fr.js ├── fr.json ├── ga.js ├── ga.json ├── gd.js ├── gd.json ├── gl.js ├── gl.json ├── he.js ├── he.json ├── hr.js ├── hr.json ├── hu.js ├── hu.json ├── hy.js ├── hy.json ├── ia.js ├── ia.json ├── id.js ├── id.json ├── is.js ├── is.json ├── it.js ├── it.json ├── ja.js ├── ja.json ├── ka.js ├── ka.json ├── ka_GE.js ├── ka_GE.json ├── km.js ├── km.json ├── kn.js ├── kn.json ├── ko.js ├── ko.json ├── lb.js ├── lb.json ├── lo.js ├── lo.json ├── lt_LT.js ├── lt_LT.json ├── lv.js ├── lv.json ├── mk.js ├── mk.json ├── mn.js ├── mn.json ├── ms_MY.js ├── ms_MY.json ├── nb.js ├── nb.json ├── nl.js ├── nl.json ├── nn_NO.js ├── nn_NO.json ├── oc.js ├── oc.json ├── pl.js ├── pl.json ├── pt_BR.js ├── pt_BR.json ├── pt_PT.js ├── pt_PT.json ├── ro.js ├── ro.json ├── ru.js ├── ru.json ├── sc.js ├── sc.json ├── si.js ├── si.json ├── sk.js ├── sk.json ├── sl.js ├── sl.json ├── sq.js ├── sq.json ├── sr.js ├── sr.json ├── sr@latin.js ├── sr@latin.json ├── sv.js ├── sv.json ├── ta.js ├── ta.json ├── th.js ├── th.json ├── tr.js ├── tr.json ├── ug.js ├── ug.json ├── uk.js ├── uk.json ├── ur_PK.js ├── ur_PK.json ├── uz.js ├── uz.json ├── vi.js ├── vi.json ├── zh_CN.js ├── zh_CN.json ├── zh_HK.js ├── zh_HK.json ├── zh_TW.js └── zh_TW.json ├── lib ├── AppInfo │ └── Application.php ├── Controller │ ├── FileHandlingController.php │ └── PublicFileHandlingController.php └── Listeners │ ├── CSPListener.php │ ├── LoadFilesScriptsListener.php │ └── LoadPublicScriptsListener.php ├── package-lock.json ├── package.json ├── tests ├── Controller │ └── FileHandlingControllerTest.php ├── SyntaxModeTest.php ├── bootstrap.php └── phpunit.xml └── webpack.config.js /.github/contributing.md: -------------------------------------------------------------------------------- 1 | ## Submitting issues 2 | 3 | If you have questions about how to install or use Nextcloud, please direct these to our [forum][forum]. We are also available on [IRC][irc]. 4 | 5 | ### Short version 6 | 7 | * The [**issue template can be found here**][template]. Please always use the issue template when reporting issues. 8 | 9 | ### Guidelines 10 | * Please search the existing issues first, it's likely that your issue was already reported or even fixed. 11 | - Go to one of the repositories, click "issues" and type any word in the top search/command bar. 12 | - You can also filter by appending e. g. "state:open" to the search string. 13 | - More info on [search syntax within github](https://help.github.com/articles/searching-issues) 14 | * This repository ([Text editor](https://github.com/nextcloud/files_texteditor/issues)) is *only* for issues within the Text editor code. 15 | * __SECURITY__: Report any potential security bug to us via [our HackerOne page](https://hackerone.com/nextcloud) or security@nextcloud.com following our [security policy](https://nextcloud.com/security/) instead of filing an issue in our bug tracker 16 | * Report the issue using our [template][template], it includes all the information we need to track down the issue. 17 | 18 | Help us to maximize the effort we can spend fixing issues and adding new features, by not reporting duplicate issues. 19 | 20 | [template]: https://raw.github.com/nextcloud/files_texteditor/master/.github/issue_template.md 21 | [forum]: https://help.nextcloud.com/ 22 | [irc]: https://webchat.freenode.net/?channels=nextcloud 23 | 24 | ### Building 25 | 26 | Webpack is used as module bundler, the project can be build by running `make` (nodejs require), 27 | `make watch` can be used to automatically rebuild the project when the source is modified. 28 | 29 | ### Contribute Code and translations 30 | Please check [server's contribution guidelines](https://github.com/nextcloud/server/blob/master/CONTRIBUTING.md#contributing-to-source-code) for further information about contributing code and translations. 31 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | day: saturday 8 | time: "03:00" 9 | timezone: Europe/Paris 10 | open-pull-requests-limit: 10 11 | - package-ecosystem: composer 12 | directory: "/" 13 | schedule: 14 | interval: weekly 15 | day: saturday 16 | time: "03:00" 17 | timezone: Europe/Paris 18 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 8 | ### Steps to reproduce 9 | 1. 10 | 2. 11 | 3. 12 | 13 | ### Expected behaviour 14 | Tell us what should happen 15 | 16 | ### Actual behaviour 17 | Tell us what happens instead 18 | 19 | ### Server configuration 20 | 23 | 24 | **Operating system**: 25 | 26 | **Web server:** 27 | 28 | **Database:** 29 | 30 | **PHP version:** 31 | 32 | **Nextcloud version:** (see Nextcloud admin page) 33 | 34 | **Where did you install Nextcloud from:** 35 | 36 | 37 | **List of activated apps:** 38 | 39 | ``` 40 | If you have access to your command line run e.g.: 41 | sudo -u www-data php occ app:list 42 | from within your Nextcloud installation folder 43 | ``` 44 | 45 | **Nextcloud configuration:** 46 | 47 | ``` 48 | If you have access to your command line run e.g.: 49 | sudo -u www-data php occ config:list system 50 | from within your Nextcloud installation folder 51 | 52 | or 53 | 54 | Insert your config.php content here 55 | Make sure to remove all sensitive content such as passwords. (e.g. database password, passwordsalt, secret, smtp password, …) 56 | ``` 57 | 58 | ### Client configuration 59 | **Browser:** 60 | 61 | **Operating system:** 62 | 63 | ### Logs 64 | 65 | #### Nextcloud log (data/owncloud.log) 66 | ``` 67 | Insert your Nextcloud log here 68 | ``` 69 | 70 | #### Browser log 71 | ``` 72 | Insert your browser log here, this could for example include: 73 | 74 | a) The javascript console log 75 | b) The network log 76 | c) ... 77 | ``` 78 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-approve-merge.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Dependabot 7 | 8 | on: 9 | pull_request_target: 10 | branches: 11 | - main 12 | - master 13 | - stable* 14 | 15 | permissions: 16 | contents: read 17 | 18 | concurrency: 19 | group: dependabot-approve-merge-${{ github.head_ref || github.run_id }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | auto-approve-merge: 24 | if: github.actor == 'dependabot[bot]' 25 | runs-on: ubuntu-latest 26 | permissions: 27 | # for hmarr/auto-approve-action to approve PRs 28 | pull-requests: write 29 | 30 | steps: 31 | - name: Disabled on forks 32 | if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} 33 | run: | 34 | echo 'Can not approve PRs from forks' 35 | exit 1 36 | 37 | # Github actions bot approve 38 | - uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2 39 | with: 40 | github-token: ${{ secrets.GITHUB_TOKEN }} 41 | 42 | # Nextcloud bot approve and merge request 43 | - uses: ahmadnassri/action-dependabot-auto-merge@45fc124d949b19b6b8bf6645b6c9d55f4f9ac61a # v2 44 | with: 45 | target: minor 46 | github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }} 47 | -------------------------------------------------------------------------------- /.github/workflows/lint-info-xml.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint info.xml 7 | 8 | on: 9 | pull_request: 10 | push: 11 | branches: 12 | - main 13 | - master 14 | - stable* 15 | 16 | permissions: 17 | contents: read 18 | 19 | concurrency: 20 | group: lint-info-xml-${{ github.head_ref || github.run_id }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | xml-linters: 25 | runs-on: ubuntu-latest 26 | 27 | name: info.xml lint 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 31 | 32 | - name: Download schema 33 | run: wget https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd 34 | 35 | - name: Lint info.xml 36 | uses: ChristophWurst/xmllint-action@39155a91429af431d65fafc21fa52ba5c4f5cb71 # v1.1 37 | with: 38 | xml-file: ./appinfo/info.xml 39 | xml-schema-file: ./info.xsd 40 | -------------------------------------------------------------------------------- /.github/workflows/lint-php-cs.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint php-cs 7 | 8 | on: pull_request 9 | 10 | permissions: 11 | contents: read 12 | 13 | concurrency: 14 | group: lint-php-cs-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | lint: 19 | runs-on: ubuntu-latest 20 | 21 | name: php-cs 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 26 | 27 | - name: Set up php 28 | uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 29 | with: 30 | php-version: 8.1 31 | coverage: none 32 | ini-file: development 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | 36 | - name: Install dependencies 37 | run: composer i 38 | 39 | - name: Lint 40 | run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) 41 | -------------------------------------------------------------------------------- /.github/workflows/lint-php.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint php 7 | 8 | on: 9 | pull_request: 10 | push: 11 | branches: 12 | - main 13 | - master 14 | - stable* 15 | 16 | permissions: 17 | contents: read 18 | 19 | concurrency: 20 | group: lint-php-${{ github.head_ref || github.run_id }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | php-lint: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | matrix: 28 | php-versions: [ "8.0", "8.1", "8.2" ] 29 | 30 | name: php-lint 31 | 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 35 | 36 | - name: Set up php ${{ matrix.php-versions }} 37 | uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 38 | with: 39 | php-version: ${{ matrix.php-versions }} 40 | coverage: none 41 | ini-file: development 42 | env: 43 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 44 | 45 | - name: Lint 46 | run: composer run lint 47 | 48 | summary: 49 | permissions: 50 | contents: none 51 | runs-on: ubuntu-latest 52 | needs: php-lint 53 | 54 | if: always() 55 | 56 | name: php-lint-summary 57 | 58 | steps: 59 | - name: Summary status 60 | run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi 61 | -------------------------------------------------------------------------------- /.github/workflows/node.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Node 7 | 8 | on: 9 | pull_request: 10 | paths: 11 | - '.github/workflows/**' 12 | - 'src/**' 13 | - 'appinfo/info.xml' 14 | - 'package.json' 15 | - 'package-lock.json' 16 | - 'tsconfig.json' 17 | - '**.js' 18 | - '**.ts' 19 | - '**.vue' 20 | push: 21 | branches: 22 | - main 23 | - master 24 | - stable* 25 | 26 | permissions: 27 | contents: read 28 | 29 | concurrency: 30 | group: node-${{ github.head_ref || github.run_id }} 31 | cancel-in-progress: true 32 | 33 | jobs: 34 | build: 35 | runs-on: ubuntu-latest 36 | 37 | name: node 38 | steps: 39 | - name: Checkout 40 | uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 41 | 42 | - name: Read package.json node and npm engines version 43 | uses: skjnldsv/read-package-engines-version-actions@8205673bab74a63eb9b8093402fd9e0e018663a1 # v2.2 44 | id: versions 45 | with: 46 | fallbackNode: '^20' 47 | fallbackNpm: '^9' 48 | 49 | - name: Set up node ${{ steps.versions.outputs.nodeVersion }} 50 | uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3 51 | with: 52 | node-version: ${{ steps.versions.outputs.nodeVersion }} 53 | 54 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }} 55 | run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}" 56 | 57 | - name: Install dependencies & build 58 | run: | 59 | npm ci 60 | npm run build --if-present 61 | 62 | - name: Check webpack build changes 63 | run: | 64 | bash -c "[[ ! \"`git status --porcelain `\" ]] || (echo 'Please recompile and commit the assets, see the section \"Show changes on failure\" for details' && exit 1)" 65 | 66 | - name: Show changes on failure 67 | if: failure() 68 | run: | 69 | git status 70 | git --no-pager diff 71 | exit 1 # make it red to grab attention 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS 2 | .DS_Store 3 | # Tests - auto-generated files 4 | /tests/coverage* 5 | /tests/clover.xml 6 | node_modules 7 | build 8 | 9 | /vendor/ 10 | 11 | .php-cs-fixer.cache 12 | -------------------------------------------------------------------------------- /.nextcloudignore: -------------------------------------------------------------------------------- 1 | /src 2 | /.git 3 | /tests 4 | /node_modules 5 | /.codecov.yml 6 | /composer.json 7 | /composer.lock 8 | /_config.yml 9 | /.drone.yml 10 | /.travis.yml 11 | /.eslintignore 12 | /.eslintrc.yml 13 | /.gitignore 14 | /issue_template.md 15 | /krankerl.toml 16 | /Makefile 17 | /mkdocs.yml 18 | /run-eslint.sh 19 | /webpack.* 20 | /img/screenshots 21 | /vendor 22 | /.github 23 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | getFinder() 12 | ->notPath('build') 13 | ->notPath('l10n') 14 | ->notPath('src') 15 | ->notPath('vendor') 16 | ->notPath('node_modules') 17 | ->in(__DIR__); 18 | return $config; 19 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | excluded_paths: 3 | - 'vendor/*' 4 | - 'js/jquery*' 5 | - 'js/vendor/*' 6 | - 'l10n/*' 7 | 8 | imports: 9 | - javascript 10 | - php 11 | 12 | tools: 13 | external_code_coverage: 14 | timeout: 1200 # Timeout in seconds. 20 minutes 15 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | lang_map = sk_SK: sk, th_TH: th, ja_JP: ja, bg_BG: bg, cs_CZ: cs, fi_FI: fi, hu_HU: hu, nb_NO: nb 4 | 5 | [o:nextcloud:p:nextcloud:r:files_texteditor] 6 | file_filter = translationfiles//files_texteditor.po 7 | source_file = translationfiles/templates/files_texteditor.pot 8 | source_lang = en 9 | type = PO 10 | 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2.15.0 4 | 5 | - Compatibility with Nextcloud 24/25 6 | - Dependency updates 7 | 8 | ## 2.14.0 9 | 10 | - Compatibility with Nextcloud 22 11 | 12 | ## 2.13.0 13 | 14 | - Compatibility with Nextcloud 21 15 | 16 | ## 2.12.0 17 | 18 | - Compatibility with Nextcloud 19 and 20 19 | - Default to preview mode when the editor is readonly (@landryb) 20 | - Correct referenced line number (@peterwvj) 21 | - Automatically detect newline mode (@ionum) 22 | - Dependency bumps 23 | 24 | ## 2.11.0 25 | 26 | - Compatibility with Nextcloud 17 and 18 27 | - Dependency bumps 28 | 29 | 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: sass build/editor.js 2 | 3 | sources=$(wildcard js/*.js) $(wildcard js/*/*.js) babel.config.js webpack.config.js 4 | 5 | sass: 6 | npm run sass 7 | 8 | .PHONY: watch 9 | watch: node_modules 10 | node_modules/.bin/webpack --watch 11 | 12 | clean: 13 | rm -rf $(build_dir) node_modules 14 | 15 | node_modules: package.json 16 | npm install 17 | 18 | build/editor.js: $(sources) node_modules 19 | NODE_ENV=production node_modules/.bin/webpack 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Texteditor 2 | 3 | [![Build Status](https://travis-ci.org/nextcloud/files_texteditor.svg?branch=master)](https://travis-ci.org/nextcloud/files_texteditor) 4 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nextcloud/files_texteditor/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/nextcloud/files_texteditor/?branch=master) 5 | [![Code Coverage](https://scrutinizer-ci.com/g/nextcloud/files_texteditor/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/nextcloud/files_texteditor/?branch=master) 6 | 7 | 8 | The original text editor app for Nextcloud, based on [Ace](http://ace.c9.io/). 9 | 10 | Features: 11 | - Syntax highlighting 12 | - Autosave 13 | - Syntax checking 14 | - Responsive design (optimised on mobile and desktop) 15 | 16 | ## Install 17 | Simply copy the `files_texteditor` folder into the `apps` directory and enable the app within the Nextcloud settings. 18 | 19 | ## Usage 20 | To use the editer, click on a [supported file](https://github.com/nextcloud/files_texteditor/blob/master/js/supported_mimetypes.json) within the Files app and the file will be loaded into the editor. Saving is automatic, but can also be triggered manually with `Ctrl+S` or `Cmd+S`. 21 | 22 | ## Contributors 23 | Maintainer: [Robin Appelman](http://github.com/icewind1991) 24 | Past contributors: [Thomas Müller](http://github.com/deepdiver1975) [Tom Needham](http://github.com/tomneedham) [Jörn Friedrich Dreyer](http://github.com/butonic) [Vincent Petry](http://github.com/pvince) 25 | 26 | 27 | Preview apps 28 | ------------ 29 | 30 | Apps can add side-by-side previews to the app for certain file types by using the preview api 31 | 32 | ```js 33 | 34 | OCA.MYApp.Preview = function(){ 35 | ... 36 | } 37 | 38 | OCA.MYApp.Preview.Prototype = { 39 | /** 40 | * Give the app the opportunity to load any resources it needs and prepare for rendering a preview 41 | */ 42 | init: function() { 43 | ... 44 | }, 45 | /** 46 | * @param {string} the text to create the preview for 47 | * @param {jQuery} the jQuery element to render the preview in 48 | */ 49 | preview: function(text, previewElement) { 50 | ... 51 | } 52 | } 53 | 54 | OCA.Files_Texteditor.registerPreviewPlugin('text/markdown', new OCA.MYApp.Preview()); 55 | 56 | ``` 57 | 58 | For styling of the preview, the preview element will have the id `preview` and the className will be set to the mimetype of the file being eddited with any slash replaced by dashes. 59 | 60 | e.g. when editing a markdown file the preview element can be styled using the `#preview.text-markdown` css query. 61 | -------------------------------------------------------------------------------- /appinfo/info.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | files_texteditor 5 | Plain text editor 6 | Open, save and edit text files 7 | This application enables Nextcloud users to open, save and edit text files in the web browser. If enabled, an entry called "Text file" in the "New" button menu at the top of the web browser appears. When clicked, a new text file opens in the browser and the file can be saved into the current Nextcloud directory. Further, when a text file is clicked in the web browser, it will be opened and editable. If the privileges allow, a user can also edit shared files and save these changes back into the web browser. 8 | More information is available in the text editor documentation. 9 | 10 | 2.15.1 11 | agpl 12 | Tom Needham, Björn Schießle 13 | FilesTextEditor 14 | office 15 | https://github.com/nextcloud/files_texteditor 16 | https://github.com/nextcloud/files_texteditor/issues 17 | https://github.com/nextcloud/files_texteditor.git 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /appinfo/routes.php: -------------------------------------------------------------------------------- 1 | 4 | * 5 | * @copyright Copyright (c) 2015, ownCloud, Inc. 6 | * @license AGPL-3.0 7 | * 8 | * This code is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License, version 3, 10 | * as published by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License, version 3, 18 | * along with this program. If not, see 19 | * 20 | */ 21 | 22 | 23 | return [ 24 | 'routes' => [ 25 | [ 26 | 'name' => 'FileHandling#load', 27 | 'url' => '/ajax/loadfile', 28 | 'verb' => 'GET' 29 | ], 30 | [ 31 | 'name' => 'FileHandling#save', 32 | 'url' => '/ajax/savefile', 33 | 'verb' => 'PUT' 34 | ], 35 | [ 36 | 'name' => 'PublicFileHandling#load', 37 | 'url' => '/public/{token}', 38 | 'verb' => 'GET' 39 | ] 40 | ] 41 | ]; 42 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['@babel/plugin-syntax-dynamic-import'], 3 | presets: [ 4 | [ 5 | '@babel/preset-env', 6 | { 7 | modules: false 8 | } 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextcloud/files_texteditor", 3 | "type": "project", 4 | "require-dev": { 5 | "phpunit/phpunit": "^9.5", 6 | "vimeo/psalm": "^5.13", 7 | "nextcloud/coding-standard": "^1.0" 8 | }, 9 | "license": "AGPL", 10 | "authors": [ 11 | { 12 | "name": "Julius Härtl", 13 | "email": "jus@bitgrid.net" 14 | } 15 | ], 16 | "scripts": { 17 | "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l", 18 | "cs:check": "php-cs-fixer fix --dry-run --diff", 19 | "cs:fix": "php-cs-fixer fix", 20 | "psalm": "psalm --threads=1", 21 | "psalm:update-baseline": "psalm --threads=1 --update-baseline --set-baseline=tests/psalm-baseline.xml", 22 | "psalm:clear": "psalm --clear-cache && psalm --clear-global-cache", 23 | "psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", 24 | "test:unit": "vendor/bin/phpunit -c tests/phpunit.xml" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /css/DroidSansMono/DroidSansMono-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/files_texteditor/24efa9c4a4e31d9e5080ee3420e3e09c0ca0c3b7/css/DroidSansMono/DroidSansMono-webfont.eot -------------------------------------------------------------------------------- /css/DroidSansMono/DroidSansMono-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/files_texteditor/24efa9c4a4e31d9e5080ee3420e3e09c0ca0c3b7/css/DroidSansMono/DroidSansMono-webfont.ttf -------------------------------------------------------------------------------- /css/DroidSansMono/DroidSansMono-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/files_texteditor/24efa9c4a4e31d9e5080ee3420e3e09c0ca0c3b7/css/DroidSansMono/DroidSansMono-webfont.woff -------------------------------------------------------------------------------- /css/DroidSansMono/Google Android License.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2008 The Android Open Source Project 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ########## 16 | 17 | This directory contains the fonts for the platform. They are licensed 18 | under the Apache 2 license. 19 | -------------------------------------------------------------------------------- /css/DroidSansMono/stylesheet.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Droid Sans Mono"; 3 | src: url("DroidSansMono-webfont.eot"); 4 | src: url("DroidSansMono-webfont.eot?#iefix") format("embedded-opentype"), url("DroidSansMono-webfont.woff") format("woff"), url("DroidSansMono-webfont.ttf") format("truetype"), url("DroidSansMono-webfont.svg#DroidSansMonoRegular") format("svg"); 5 | font-weight: normal; 6 | font-style: normal; 7 | } 8 | 9 | /*# sourceMappingURL=stylesheet.css.map */ 10 | -------------------------------------------------------------------------------- /css/DroidSansMono/stylesheet.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["stylesheet.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EACA;EAIA;EACA","file":"stylesheet.css"} -------------------------------------------------------------------------------- /css/DroidSansMono/stylesheet.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Droid Sans Mono'; 3 | src: url('DroidSansMono-webfont.eot'); 4 | src: url('DroidSansMono-webfont.eot?#iefix') format('embedded-opentype'), 5 | url('DroidSansMono-webfont.woff') format('woff'), 6 | url('DroidSansMono-webfont.ttf') format('truetype'), 7 | url('DroidSansMono-webfont.svg#DroidSansMonoRegular') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /css/merged.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["DroidSansMono/stylesheet.scss","style.scss","mobile.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EACA;EAIA;EACA;;ACRJ;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACI;;;AAGJ;EACC;EACA;EACC;;;AAGF;EACC;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;AAAA;EAEC;;;AAGD;EAEC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;;;AAGD;EACC;;;AAED;EACE;;;AAGF;AAAA;EAEC;;;AAGD;EACC;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;IACC;IACA;IACA;IACA;IACA;IACA;;EAGD;IACC;;EAGD;IACC;;EAGD;IACC;;EAGD;IACC;;EAGD;IACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;AACA;EACC;;;AAGD;EACC;;;AAGD;EACC;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;AAAA;EAEC;EACA;;;AAGD;EACC;EACA;EACA;;;AAGD;EACC;EACA;;;ACxPD;AAGA;EACA;AAAA;IAEC","file":"merged.css"} -------------------------------------------------------------------------------- /css/merged.scss: -------------------------------------------------------------------------------- 1 | @import 'DroidSansMono/stylesheet.scss'; 2 | @import 'style.scss'; 3 | @import 'mobile.scss'; 4 | -------------------------------------------------------------------------------- /css/mobile.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 768px) { 2 | /* hide search function on mobile to prevent wrap of elements */ 3 | #editorsearchval, 4 | #editor_save + label { 5 | display: none !important; 6 | } 7 | } 8 | 9 | /*# sourceMappingURL=mobile.css.map */ 10 | -------------------------------------------------------------------------------- /css/mobile.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["mobile.scss"],"names":[],"mappings":"AAAA;AAGA;EACA;AAAA;IAEC","file":"mobile.css"} -------------------------------------------------------------------------------- /css/mobile.scss: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 768px) { 2 | 3 | 4 | /* hide search function on mobile to prevent wrap of elements */ 5 | #editorsearchval, 6 | #editor_save+label { 7 | display: none !important; 8 | } 9 | 10 | 11 | } -------------------------------------------------------------------------------- /css/public-share.css: -------------------------------------------------------------------------------- 1 | .preview.formatted-text { 2 | max-width: 810px; 3 | padding: 0px 20px !important; 4 | box-sizing: border-box; 5 | font-size: 18px; 6 | line-height: 1.6em; 7 | min-height: 440px; 8 | color: #333; 9 | text-align: left; 10 | margin-bottom: 170px !important; 11 | } 12 | .preview.formatted-text h1, 13 | .preview.formatted-text h2, 14 | .preview.formatted-text h3 { 15 | margin-top: 1em; 16 | word-wrap: break-word; 17 | } 18 | .preview.formatted-text h1 { 19 | line-height: 1.1em; 20 | margin-bottom: 1em; 21 | text-align: center; 22 | font-size: 3em; 23 | } 24 | .preview.formatted-text h2 { 25 | line-height: 1.1em; 26 | margin-bottom: 0.5em; 27 | font-size: 2em; 28 | } 29 | .preview.formatted-text h3 { 30 | line-height: 1.1em; 31 | margin-bottom: 0.6em; 32 | font-size: 1.4em; 33 | } 34 | .preview.formatted-text p, 35 | .preview.formatted-text ul, 36 | .preview.formatted-text ol, 37 | .preview.formatted-text pre { 38 | line-height: 1.45em; 39 | } 40 | .preview.formatted-text p, 41 | .preview.formatted-text details { 42 | margin-bottom: 17.6px; 43 | } 44 | .preview.formatted-text ul, 45 | .preview.formatted-text ol { 46 | padding-left: 25px; 47 | } 48 | .preview.formatted-text ul { 49 | list-style-type: disc; 50 | } 51 | .preview.formatted-text ul ul { 52 | list-style-type: circle; 53 | } 54 | .preview.formatted-text a { 55 | color: #448ac9; 56 | text-decoration: none; 57 | } 58 | .preview.formatted-text a:hover, 59 | .preview.formatted-text a:focus, 60 | .preview.formatted-text a:active { 61 | text-decoration: underline; 62 | } 63 | .preview.formatted-text em { 64 | opacity: 1; 65 | font-style: italic; 66 | } 67 | .preview.formatted-text code { 68 | background-color: rgb(242, 242, 242); 69 | border-radius: 3px; 70 | padding: 5px 12px; 71 | display: block; 72 | white-space: pre; 73 | overflow: auto; 74 | } 75 | 76 | /* hide image preview during loading or if it renders fine */ 77 | .icon-loading .text-preview, 78 | .preview .text-preview:not(.default-overridden) { 79 | display: none !important; 80 | } 81 | 82 | /*# sourceMappingURL=public-share.css.map */ 83 | -------------------------------------------------------------------------------- /css/public-share.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["public-share.scss"],"names":[],"mappings":"AAAA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;EAGC;EACA;;AAGD;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;AAAA;AAAA;AAAA;EAIC;;AAED;AAAA;EAEC;;AAED;AAAA;EAEC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;EACA;;AAED;AAAA;AAAA;EAGC;;AAGD;EACC;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;;;AAIF;AACA;AAAA;EAEC","file":"public-share.css"} -------------------------------------------------------------------------------- /css/public-share.scss: -------------------------------------------------------------------------------- 1 | .preview.formatted-text { 2 | max-width: 810px; 3 | padding: 0px 20px !important; 4 | box-sizing: border-box; 5 | font-size: 18px; 6 | line-height: 1.6em; 7 | min-height: 440px; 8 | color: #333; 9 | text-align: left; 10 | margin-bottom: 170px !important; 11 | 12 | h1, 13 | h2, 14 | h3 { 15 | margin-top: 1em; 16 | word-wrap: break-word; 17 | } 18 | 19 | h1 { 20 | line-height: 1.1em; 21 | margin-bottom: 1em; 22 | text-align: center; 23 | font-size: 3em; 24 | } 25 | 26 | h2 { 27 | line-height: 1.1em; 28 | margin-bottom: .5em; 29 | font-size: 2em; 30 | } 31 | 32 | h3 { 33 | line-height: 1.1em; 34 | margin-bottom: .6em; 35 | font-size: 1.4em; 36 | } 37 | 38 | p, 39 | ul, 40 | ol, 41 | pre { 42 | line-height: 1.45em; 43 | } 44 | p, 45 | details { 46 | margin-bottom: 17.6px; 47 | } 48 | ul, 49 | ol { 50 | padding-left: 25px; 51 | } 52 | 53 | ul { 54 | list-style-type: disc; 55 | } 56 | 57 | ul ul { 58 | list-style-type: circle; 59 | } 60 | 61 | a { 62 | color: #448ac9; 63 | text-decoration: none; 64 | } 65 | a:hover, 66 | a:focus, 67 | a:active { 68 | text-decoration: underline; 69 | } 70 | 71 | em { 72 | opacity: 1; 73 | font-style: italic; 74 | } 75 | 76 | code { 77 | background-color: rgb(242, 242, 242); 78 | border-radius: 3px; 79 | padding: 5px 12px; 80 | display: block; 81 | white-space: pre; 82 | overflow: auto; 83 | } 84 | } 85 | 86 | /* hide image preview during loading or if it renders fine */ 87 | .icon-loading .text-preview, 88 | .preview .text-preview:not(.default-overridden) { 89 | display: none !important; 90 | } 91 | -------------------------------------------------------------------------------- /css/style.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAAA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACI;;;AAGJ;EACC;EACA;EACC;;;AAGF;EACC;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;AAAA;EAEC;;;AAGD;EAEC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;;;AAGD;EACC;;;AAED;EACE;;;AAGF;AAAA;EAEC;;;AAGD;EACC;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;IACC;IACA;IACA;IACA;IACA;IACA;;EAGD;IACC;;EAGD;IACC;;EAGD;IACC;;EAGD;IACC;;EAGD;IACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;AACA;EACC;;;AAGD;EACC;;;AAGD;EACC;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;AAAA;EAEC;EACA;;;AAGD;EACC;EACA;EACA;;;AAGD;EACC;EACA","file":"style.css"} -------------------------------------------------------------------------------- /img/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/files_texteditor/24efa9c4a4e31d9e5080ee3420e3e09c0ca0c3b7/img/app.png -------------------------------------------------------------------------------- /img/app.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /img/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/text.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /js/ImportAce.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @copyright Copyright (c) 2019 Julius Härtl 3 | * 4 | * @author Julius Härtl 5 | * 6 | * @license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default function() { 24 | return import(/* webpackChunkName: "ace" */'brace') 25 | } 26 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ownCloud - Files_Texteditor 3 | * 4 | * This file is licensed under the Affero General Public License version 3 or 5 | * later. See the COPYING file. 6 | * 7 | * @author Tom Needham 8 | * @copyright Tom Needham 2015 9 | */ 10 | 11 | import {SidebarPreview} from './sidebarpreview'; 12 | import {Texteditor} from './editor'; 13 | import {newFileMenuPlugin} from './newfileplugin'; 14 | 15 | // convince webpack to load chunks 16 | __webpack_require__.p = OC.filePath('files_texteditor', 'js', '../build/'); 17 | const script = document.querySelector('[nonce]'); 18 | __webpack_require__.nc = script['nonce'] || script.getAttribute('nonce'); 19 | 20 | OCA.Files_Texteditor = Texteditor; 21 | 22 | OC.Plugins.register('OCA.Files.NewFileMenu', newFileMenuPlugin); 23 | OC.Plugins.register('OCA.Files.SidebarPreviewManager', new SidebarPreview()); 24 | 25 | $(document).ready(function () { 26 | $('#editor').remove(); 27 | OCA.Files_Texteditor.initialize($('
')); 28 | }); 29 | -------------------------------------------------------------------------------- /js/newfileplugin.js: -------------------------------------------------------------------------------- 1 | export const newFileMenuPlugin = { 2 | 3 | attach: function (menu) { 4 | var fileList = menu.fileList; 5 | 6 | // Make text app handle new file creation if enabled 7 | if (typeof OCA.Text !== 'undefined') { 8 | return; 9 | } 10 | 11 | // only attach to main file list, public view is not supported yet 12 | if (fileList.id !== 'files') { 13 | return; 14 | } 15 | 16 | // register the new menu entry 17 | menu.addMenuEntry({ 18 | id: 'file', 19 | displayName: t('files_texteditor', 'New text file'), 20 | templateName: t('files_texteditor', 'New text file.txt'), 21 | iconClass: 'icon-filetype-text', 22 | fileType: 'file', 23 | actionHandler: function (name) { 24 | var dir = fileList.getCurrentDirectory(); 25 | // first create the file 26 | fileList.createFile(name).then(function () { 27 | // once the file got successfully created, 28 | // open the editor 29 | OCA.Files_Texteditor._onEditorTrigger( 30 | name, 31 | { 32 | fileList: fileList, 33 | dir: dir 34 | } 35 | ); 36 | }); 37 | } 38 | }); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /js/sidebarpreview.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 3 | * 4 | * This file is licensed under the Affero General Public License version 3 5 | * or later. 6 | * 7 | * See the COPYING-README file. 8 | * 9 | */ 10 | 11 | import {getSyntaxMode} from "./SyntaxMode"; 12 | import importAce from './ImportAce'; 13 | 14 | /** @type array[] supportedMimeTypes */ 15 | const supportedMimeTypes = require('./supported_mimetypes.json'); 16 | 17 | export class SidebarPreview { 18 | attach (manager) { 19 | const handler = this.handlePreview.bind(this); 20 | supportedMimeTypes.forEach(value => manager.addPreviewHandler(value, handler)); 21 | } 22 | 23 | handlePreview (model, $thumbnailDiv, $thumbnailContainer, fallback) { 24 | const previewWidth = $thumbnailContainer.parent().width() + 50; // 50px for negative margins 25 | const previewHeight = previewWidth / (16 / 9); 26 | 27 | this.getFileContent(model.getFullPath()).then(function (content) { 28 | content = content.filecontents; 29 | $thumbnailDiv.removeClass('icon-loading icon-32'); 30 | $thumbnailContainer.addClass('large'); 31 | $thumbnailContainer.addClass('text'); 32 | const $editorDiv = $("