remark-file-attachment
v1.0.4
Published
Remark plugin to embed files in markdown, as more than just a link.
Downloads
8
Maintainers
Readme
Remark File Attachment Plugin
This is a plugin for Remark, and allows you to embed file attachments in markdown files. The plugin offers the ability to style the file attachments, so that they look like more than a simple link, and arguably it offers better accessability as well. This plugin can also be used with Gridsome.
Installation
npm i remark-file-attachment --save-dev
# yarn add remark-file-attachment --dev
Configuration
Structure
You can configure the HTML element type to be used for the attachment container and the attachment item.
- Attachment container (default ul)
containerElement: "ul",
- Attachment item (default li)
containerElement: "li",
Styling
You can provide css and styles for just about all of the attachment's HTML elements.
Attachment container (default ul)
containerCss: "border border-gray-200 rounded-md divide-y divide-gray-200 max-w-lg mb-3", containerStyle: "list-style: none !important; margin-top: 0 !important; margin-bottom: 0 !important;",
Attachment item (default li)
itemCss: "pr-4 py-3 flex items-center justify-between text-sm text-gray-400 focus-within:text-blue-600", itemStyle: "content: none; position: static !important; margin-top: 0 !important; margin-bottom: 0 !important; padding-left: 0.75rem !important;",
Icon and paragraph container (div)
iconAndParagraphContainerCss: "flex items-center max-w-32 md:max-w-max pr-4",
Paragraph (span)
paragraphCss: "ml-2 truncate text-gray-800 max-w-xs",
Link container (div)
linkContainerCss: "ml-3 inline-flex space-x-4",
Show link (a)
showLinkCss: "font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline", showLinkStyle: "text-decoration: none;",
Download link (a)
downloadLinkCss: "font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline", downloadLinkStyle: "text-decoration: none;",
Icon
You can provide HTML for an icon next to the attachment name (paragraph).
Example:
iconHTML: `
<svg focusable="false" aria-hidden="true" class="flex-shrink-0 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd" />
</svg>
`,
Alignment
If you want alignment to work, you'll have to supply css classes.
There's three options:
cssClassToCenterPlaceholder
Example value
w-full flex justify-center
cssClassToLeftAlignPlaceholder
Example value
w-full flex justify-start
cssClassToRightAlignPlaceholder
Example value
w-full flex justify-end
Note: You can also add extra css, like bottom margin, to space things out nicely.
Link text & alt text
You can provide text to use for the "Show" and "Download" link, so thay they fit with the locale of the webiste.
showLinkText: "Show",
showLinkAltSuffix: "in new tab",
// The alt text of the show link will be showLinkText + " " + attachment text attribute + showLinkAltSuffix.
// Show Document 1.pdf in new tab
downloadLinkText: "Download",
// The alt text of the download link will be downloadLinkText + " " + attachment text attribute.
// Download Document 1.pdf
Remark configuration:
const remark = require("remark");
const fileAttachment = require("remark-file-attachment");
const processor = remark().use(fileAttachment, {
cssClassToCenter: "w-full flex justify-center",
cssClassToLeftAlign: "w-full flex justify-start",
cssClassToRightAlign: "w-full flex justify-end",
containerElement: "ul",
containerCss: "border border-gray-200 rounded-md divide-y divide-gray-200 max-w-lg mb-3",
containerStyle: "list-style: none !important; margin-top: 0 !important; margin-bottom: 0 !important;",
itemElement: "li",
itemCss: "pr-4 py-3 flex items-center justify-between text-sm text-gray-400 focus-within:text-blue-600",
itemStyle: "content: none; position: static !important; margin-top: 0 !important; margin-bottom: 0 !important; padding-left: 0.75rem !important;",
iconHTML: `
<svg focusable="false" aria-hidden="true" class="flex-shrink-0 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd" />
</svg>
`,
paragraphCss: "ml-2 truncate text-gray-800 max-w-xs",
iconAndParagraphContainerCss: "flex items-center max-w-32 md:max-w-max pr-4",
linkContainerCss: "ml-3 inline-flex space-x-4",
showLinkText: "Show",
showLinkAltTextSuffix: "in new tab",
showLinkCss: "font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline",
downloadLinkText: "Download",
downloadLinkCss: "font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline",
downloadLinkStyle: "text-decoration: none;",
});
Gridsome configuration:
module.exports = {
plugins: [
{
use: "@gridsome/source-filesystem",
options: {
path: "blog/**/*.md",
route: "/blog/:year/:month/:day/:slug",
remark: {
plugins: [
[
"remark-file-attachment",
{
cssClassToCenter: "w-full flex justify-center",
cssClassToLeftAlign: "w-full flex justify-start",
cssClassToRightAlign: "w-full flex justify-end",
containerElement: "ul",
containerCss: "border border-gray-200 rounded-md divide-y divide-gray-200 max-w-lg mb-3",
containerStyle: "list-style: none !important; margin-top: 0 !important; margin-bottom: 0 !important;",
itemElement: "li",
itemCss: "pr-4 py-3 flex items-center justify-between text-sm text-gray-400 focus-within:text-blue-600",
itemStyle: "content: none; position: static !important; margin-top: 0 !important; margin-bottom: 0 !important; padding-left: 0.75rem !important;",
iconHTML: `
<svg focusable="false" aria-hidden="true" class="flex-shrink-0 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd" />
</svg>
`,
paragraphCss: "ml-2 truncate text-gray-800 max-w-xs",
iconAndParagraphContainerCss: "flex items-center max-w-32 md:max-w-max pr-4",
linkContainerCss: "ml-3 inline-flex space-x-4",
showLinkText: "Show",
showLinkAltTextSuffix: "in new tab",
showLinkCss: "font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline",
downloadLinkText: "Download",
downloadLinkCss: "font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline",
downloadLinkStyle: "text-decoration: none;",
},
]
]
}
}
}
]
}
Usage in markdown
The markdown must consist of all the possible attributes (attachment, text & placement), and you must enclose the markdown in backticks (`).
Format:
`attachment [FILE_LINK] text [TEXT] placement [Left|Center|Right]`
Examples:
`attachment /uploads/salesoverview.pdf text Sales overview report placement Left end`
or
`attachment /uploads/salesoverview.pdf text Sales overview report placement Left end attachment /uploads/purchaseoverview.pdf text Purchase overview report placement Left end`
Output
Attachment/s
This is how the attachment/s can appear on the screen:
Generated HTML
<div class="w-full flex justify-start">
<ul class="border border-gray-200 rounded-md divide-y divide-gray-200 max-w-lg mb-3" style="list-style: none !important; margin-top: 0 !important; margin-bottom: 0 !important;">
<li class="pr-4 py-3 flex items-center justify-between text-sm text-gray-400 focus-within:text-blue-600" style="content: none; position: static !important; margin-top: 0 !important; margin-bottom: 0 !important; padding-left: 0.75rem !important;">
<div class="flex items-center max-w-32 md:max-w-max pr-4" style="">
<svg focusable="false" aria-hidden="true" class="flex-shrink-0 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd"></path></svg>
<span class="ml-2 truncate text-gray-800 max-w-xs" style="">Sales overview report</span>
</div>
<div class="ml-3 inline-flex space-x-4" style="">
<a href="/uploads/salesoverview-report.pdf" target="_blank" rel="noopener noreferrer" aria-label="Show attachment in new tab" class="font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline">Show</a>
<a href="/uploads/salesoverview-report.pdf" download="" aria-label="Download attachment" class="font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline">Download</a>
</div>
</li>
<li class="pr-4 py-3 flex items-center justify-between text-sm text-gray-400 focus-within:text-blue-600" style="content: none; position: static !important; margin-top: 0 !important; margin-bottom: 0 !important; padding-left: 0.75rem !important;">
<div class="flex items-center max-w-32 md:max-w-max pr-4" style="">
<svg focusable="false" aria-hidden="true" class="flex-shrink-0 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd"></path></svg>
<span class="ml-2 truncate text-gray-800 max-w-xs" style="" title="Purchase overview report">Purchase overview report</span>
</div>
<div class="ml-3 inline-flex space-x-4" style="">
<a href="/uploads/purchaseoverview-report.pdf" target="_blank" rel="noopener noreferrer" aria-label="Show Purchase overview report in new tab" class="font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline">Show</a>
<a href="/uploads/purchaseoverview-report.pdf" download="" aria-label="Download Purchase overview report" class="font-medium text-blue-600 hover:text-blue-500 outline-none focus:underline">Download</a>
</div>
</li>
</ul>
</div>
Errors
When the plugin detects errors, i.e. an incorrectly formatted attachment element, it will render a red fat error instead of the attachment.
License
MIT