/* * Copyright (c) 2011-2014 Julien Nicoulaud <julien.nicoulaud@gmail.com> * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package net.nicoulaj.idea.markdown.editor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import javax.swing.text.Element; import javax.swing.text.StyleConstants; import javax.swing.text.View; import javax.swing.text.ViewFactory; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.ImageView; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import static net.nicoulaj.idea.markdown.editor.MarkdownPathResolver.resolveRelativePath; /** * {@link HTMLEditorKit} that can display images with paths relative to the document. * * @author Roger Grantham (https://github.com/grantham) * @author Julien Nicoulaud <julien.nicoulaud@gmail.com> * @since 0.8 */ public class MarkdownEditorKit extends HTMLEditorKit { /** The document. */ private final Document document; /** * Build a new instance of {@link MarkdownEditorKit}. * * @param document the document */ public MarkdownEditorKit(@NotNull Document document) { this.document = document; } /** * Creates a copy of the editor kit. * * @return a new {@link MarkdownEditorKit} instance */ @Override public Object clone() { return new MarkdownEditorKit(document); } /** {@inheritDoc} */ @Override public ViewFactory getViewFactory() { return new MarkdownViewFactory(document); } /** * An {@link HTMLFactory} that uses {@link MarkdownImageView} for images. * * @author Roger Grantham (https://github.com/grantham) * @author Julien Nicoulaud <julien.nicoulaud@gmail.com> * @since 0.8 */ private static class MarkdownViewFactory extends HTMLFactory { /** The document. */ private final Document document; /** * Build a new instance of {@link MarkdownViewFactory}. * * @param document the document */ private MarkdownViewFactory(Document document) { this.document = document; } @Override public View create(Element elem) { if (HTML.Tag.IMG.equals(elem.getAttributes().getAttribute(StyleConstants.NameAttribute))) return new MarkdownImageView(document, elem); return super.create(elem); } } /** * An {@link ImageView} that can resolve the image URL relative to the document. * * @author Roger Grantham (https://github.com/grantham) * @since 0.8 */ private static class MarkdownImageView extends ImageView { /** The document. */ private final Document document; /** * Build a new instance of {@link MarkdownImageView}. * * @param document the document * @param elem the element to create a view for */ private MarkdownImageView(@NotNull Document document, @NotNull Element elem) { super(elem); this.document = document; } /** * Return a URL for the image source, or null if it could not be determined. * <p/> * Calls {@link javax.swing.text.html.ImageView#getImageURL()}, tries to resolve the relative if needed. * * @return a URL for the image source, or null if it could not be determined. */ @Override public URL getImageURL() { final String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC); final VirtualFile localImage = resolveRelativePath(document, src); try { if (localImage != null && localImage.exists()) return new File(localImage.getPath()).toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } return super.getImageURL(); } } }