├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── lib └── main.coffee └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.9 2 | 3 | * Add support for disabling prepending the target file to the copied image 4 | 5 | ## 0.1.8 6 | 7 | * Add support for per-file asset directories (#6) 8 | * Add support for html markup (#6) 9 | 10 | ## 0.1.7 11 | 12 | * Add support for custom image directories 13 | 14 | ## 0.1.6 15 | 16 | * Add support for preserving original file names on drag and drop 17 | 18 | ## 0.1.0 - First Release 19 | * Initial version 20 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Tamas Nagy 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [atom-markdown-image-assistant](https://atom.io/packages/markdown-image-assistant) 2 | 3 | Add sane drag and drop and copy/paste support for images to markdown 4 | files. This is especially useful for notetaking in Atom. 5 | 6 | ![](https://cloud.githubusercontent.com/assets/1661487/19503385/137f1da6-9568-11e6-9796-910e6927459d.gif) 7 | 8 | ## Atom Settings 9 | 10 | These settings can be accessed under Settings -> Packages -> Markdown 11 | Image Assistant. 12 | 13 | ### Default Settings 14 | 15 | Whenever an image is dragged and dropped or copy and pasted on an open markdown file, this package automatically copies it to an `assets/` folder in the current directory, renames the image, and inserts a relative link to the image. 16 | 17 | ### Active file types 18 | 19 | File type that image assistant should activate for 20 | 21 | ### Image directory 22 | 23 | Default image directory 24 | 25 | ### Preserve original file names 26 | 27 | When dragging and dropping files, whether to preserve original file names when copying over into the image directory 28 | 29 | ### Use the Markdown filename 30 | 31 | Creates an asset folder in the form of `.assets/`. Where 32 | `` is the root of the file without the supported Markdown extensions (`.markdown`, `.md`, `.mdown`, `.mkd`, `.mkdow`). 33 | 34 | 35 | ### Insert image as Markup, instead of Markdown 36 | 37 | Insert an image as HTML Markup, ``, instead of Markdown, `![]()`. Useful if you want to adjust image `width` or `height` 38 | 39 | ----- 40 | 41 | 42 | ## Installation 43 | 44 | This plugin can be installed via Atom's GUI or via the command line: 45 | 46 | ``` 47 | apm install markdown-image-assistant 48 | ``` 49 | 50 | 51 | ### Demo 52 | * My Cat folder name 53 | ``` 54 | ![](CAT-assets/README-684b45a8.jpg) 55 | ``` 56 | 57 | * Markup 58 | ``` 59 | README-684b45a8.jpg 60 | ``` 61 | * Per-file asset directory 62 | ``` 63 | ![](README.assets/README-684b45a8.jpg) 64 | ``` 65 | 66 | * Preserve Original filename 67 | ``` 68 | ![](README.assets/README-Fort-*ssHole.jpg) 69 | ``` 70 | 71 | ----- 72 | ![atom-image-assistant](https://cloud.githubusercontent.com/assets/118112/24306827/2db2494a-107f-11e7-969a-2581851aa816.gif) 73 | -------------------------------------------------------------------------------- /lib/main.coffee: -------------------------------------------------------------------------------- 1 | {CompositeDisposable, Directory, File} = require 'atom' 2 | fs = require 'fs' 3 | path = require 'path' 4 | crypto = require "crypto" 5 | 6 | defaultImageDir = "assets/" 7 | 8 | module.exports = MarkdownImageAssistant = 9 | subscriptions: null 10 | config: 11 | suffixes: 12 | title: "Active file types" 13 | description: "File type that image assistant should activate for" 14 | type: 'array' 15 | default: ['.markdown', '.md', '.mdown', '.mkd', '.mkdow'] 16 | items: 17 | type: 'string' 18 | preserveOrigName: 19 | title: "Preserve original file names" 20 | description: "When dragging and dropping files, whether to perserve original file names when copying over into the image directory" 21 | type: 'boolean' 22 | default: false 23 | prependTargetFileName: 24 | title: "Prepend the target file name" 25 | description: "Whether to prepend the target file name when copying over the image. Overrides the \"Preserve Original Name\" setting." 26 | type: 'boolean' 27 | default: true 28 | preserveFileNameInAssetsFolder: 29 | title: "Create per-file asset directories" 30 | description: "Creates a separate asset directory for each markdown file, e.g. `README.assets/`; setting `Image Directory` to a value other than the default of `assets/` overrides this option" 31 | type: 'boolean' 32 | default: false 33 | imageDir: 34 | title: "Image directory" 35 | description: "Local directory to copy images into; created if not found." 36 | type: 'string' 37 | default: defaultImageDir 38 | insertHtmlOverMarkdown: 39 | title: "Insert image as Markup, instead of Markdown" 40 | description: "Insert an image as HTML Markup, ``, instead of Markdown, `![]()`. Useful if you want to adjust image `width` or `height`" 41 | type: 'boolean' 42 | default: false 43 | 44 | activate: (state) -> 45 | # Events subscribed to in atom's system can be easily cleaned up 46 | # with a CompositeDisposable 47 | @subscriptions = new CompositeDisposable 48 | 49 | # Register handler for drag 'n drop events 50 | @subscriptions.add atom.workspace.observeTextEditors (editor) => @handle_subscription(editor) 51 | # Register handler for copy and paste events 52 | @subscriptions.add atom.commands.onWillDispatch (e) => 53 | if event? and event.type == 'core:paste' 54 | editor = atom.workspace.getActiveTextEditor() 55 | return unless editor 56 | @handle_cp(e) 57 | 58 | handle_subscription: (editor) -> 59 | textEditorElement = atom.views.getView editor 60 | # on drag and drop event 61 | textEditorElement.addEventListener "drop", (e) => @handle_dropped(e) 62 | 63 | # triggered in response to dragged and dropped files 64 | handle_dropped: (e) -> 65 | e.preventDefault?() 66 | e.stopPropagation?() 67 | editor = atom.workspace.getActiveTextEditor() 68 | return unless editor 69 | 70 | dropped_files = e.dataTransfer.files 71 | 72 | for f in dropped_files 73 | if fs.lstatSync(f.path).isFile() 74 | imgbuffer = new Buffer(fs.readFileSync(f.path)) 75 | extname = path.extname(String(f.path)) 76 | if atom.config.get('markdown-image-assistant.preserveOrigName') 77 | origname = path.basename(f.path, extname) 78 | else 79 | origname = "" 80 | @process_file(editor, imgbuffer, extname, origname) 81 | 82 | # triggered in response to a copy pasted image 83 | handle_cp: (e) -> 84 | clipboard = require 'clipboard' 85 | img = clipboard.readImage() 86 | return if img.isEmpty() 87 | editor = atom.workspace.getActiveTextEditor() 88 | e.stopImmediatePropagation() 89 | if Number process.versions.electron[0] >= 2 90 | imgbuffer = img.toPNG() 91 | else 92 | imgbuffer = img.toPng() 93 | @process_file(editor, imgbuffer, ".png", "") 94 | 95 | # write a given buffer to the local "assets/" directory 96 | process_file: (editor, imgbuffer, extname, origname) -> 97 | target_file = editor.getPath() 98 | 99 | if path.extname(target_file) not in atom.config.get('markdown-image-assistant.suffixes') 100 | console.log "Adding images to non-markdown files is not supported" 101 | return false 102 | 103 | if atom.config.get('markdown-image-assistant.imageDir') == defaultImageDir && atom.config.get('markdown-image-assistant.preserveFileNameInAssetsFolder') 104 | assets_dir = path.basename(path.parse(target_file).name + "." + atom.config.get('markdown-image-assistant.imageDir')) 105 | else 106 | assets_dir = path.basename(atom.config.get('markdown-image-assistant.imageDir')) 107 | assets_path = path.join(target_file, "..", assets_dir) 108 | 109 | md5 = crypto.createHash 'md5' 110 | md5.update(imgbuffer) 111 | 112 | if !atom.config.get('markdown-image-assistant.prependTargetFileName') 113 | if origname != "" 114 | img_filename = "#{origname}#{extname}" 115 | else 116 | img_filename = "#{md5.digest('hex').slice(0,8)}#{extname}" 117 | else if origname == "" 118 | img_filename = "#{path.parse(target_file).name}-#{md5.digest('hex').slice(0,8)}#{extname}" 119 | else 120 | img_filename = "#{path.parse(target_file).name}-#{origname}#{extname}" 121 | console.log img_filename 122 | 123 | @create_dir assets_path, ()=> 124 | fs.writeFile path.join(assets_path, img_filename), imgbuffer, 'binary', ()=> 125 | console.log "Copied file over to #{assets_path}" 126 | if atom.config.get('markdown-image-assistant.insertHtmlOverMarkdown') 127 | editor.insertText "\"#{img_filename}\"" 128 | else 129 | editor.insertText "![](#{assets_dir}/#{img_filename})" 130 | 131 | return false 132 | 133 | create_dir: (dir_path, callback)=> 134 | dir_handle = new Directory(dir_path) 135 | 136 | dir_handle.exists().then (existed) => 137 | if not existed 138 | dir_handle.create().then (created) => 139 | if created 140 | console.log "Successfully created #{dir_path}" 141 | callback() 142 | else 143 | callback() 144 | 145 | deactivate: -> 146 | @subscriptions.dispose() 147 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "markdown-image-assistant", 3 | "main": "./lib/main", 4 | "version": "0.2.2", 5 | "description": "Add sane drag and drop and copy/paste support for images to markdown files", 6 | "keywords": [ 7 | "markdown", 8 | "drag", 9 | "drop", 10 | "image", 11 | "embed", 12 | "copy", 13 | "paste" 14 | ], 15 | "repository": "https://github.com/tlnagy/atom-markdown-image-assistant", 16 | "license": "MIT", 17 | "engines": { 18 | "atom": ">=1.0.0 <2.0.0" 19 | }, 20 | "dependencies": {} 21 | } 22 | --------------------------------------------------------------------------------