【优雅写博客】hexo图片相对路径与开头模板处理
在hexo静态博客部署中,图片的显示一直困扰我,之前几次搞博客也常常遇到图片显示不了的问题,今天来解决一下。还有对于butterfly主题的博文开头的自动生成,因为我写博客一般习惯是手动创建markdown文件,写那个开头觉得挺烦的,索性就一起解决了。
图片展示
前提环境
hexo+butterfly
typora
jdk8
idea
前置了解
首先,markdown的图片可以通过以下两种方式展示:
1 <img src ="图片路劲" alt ="图片描述" />
但是很遗憾,hexo并不支持。所以,比较痛苦的,我们在推博文上去时候必须把图片路径转化成hexo识别的了的。
下面这种就是hexo能够识别的语法
1 {% asset_img 8248398428fb42d78c3313cf4578e10f.png 图片描述 %}
准备工作
hexo默认不支持文章资源文件夹,需要先去开下配置。
在hexo中使用文章资源文件夹 需要在config.yaml
文件中更改一下配置:
当该配置被应用后,使用hexo new
命令创建新文章时,会生成相同名字的文件夹,也就是文章资源文件夹。
在typora中修改设置,改变图片的复制存储路径
然后这样我们每次粘贴图片就可以自动放入与md文件同名的文件夹了。
了解主题的博客开头格式,如我在用的butterfly主题就是下面这个开头
1 2 3 4 5 6 --- title: date: tags: [未分类] categories: [未分类] ---
这里是个易错点,我配了好久。就是冒号要是英文的,然后冒号后面需要有一个空格。分类和标签要加[],如果有多个分类用","隔开。当然,具体主题应该有样例可以参照。
实现markdown适应hexo
简单来说就是用java进行正则的匹配替换,然后加入模板开头。
下面就是java代码的实现。
这个类运行第一次会把模板写入没写模板的markdown中,注意 :输入文件输出文件都会被写入 ,同时替换两种markdown的图片显示格式成Hexo能够识别的格式。然后运行第二次会把模板中的空值写入默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 import java.io.*;import java.nio.file.*;import java.nio.file.attribute.BasicFileAttributes;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import java.util.regex.*;public class MarkdownImageConverter { public static void main (String[] args) { String inputFolder = "A:\\usr\\MyBlog\\RawBlog" ; String outputFolder = "A:\\usr\\MyBlog\\CrazylycheeBlog\\source\\_posts" ; addTheHexoBegin(inputFolder); File inputDir = new File (inputFolder); File outputDir = new File (outputFolder); if (!outputDir.exists()) { outputDir.mkdirs(); } File[] files = inputDir.listFiles((dir, name) -> name.endsWith(".md" )); if (files != null ) { for (File file : files) { try { convertFile(file, outputDir); copyRelatedFolder(file, inputDir, outputDir); } catch (IOException e) { e.printStackTrace(); } } } } private static void convertFile (File inputFile, File outputDir) throws IOException { String content = new String (Files.readAllBytes(inputFile.toPath())); String name = inputFile.getName().replaceAll("\\.md$" , "" ); String redix1 = "<img src=\"" +name+"/([^/][^\"]+)\" alt=\"([^\"]+)\" />" ; String redix2 = "!\\[([^\\]]+)\\]\\(" +name+"/([^/][^\\)]+)\\)" ; Pattern htmlPattern = Pattern.compile(redix1); Matcher htmlMatcher = htmlPattern.matcher(content); StringBuffer sb = new StringBuffer (); while (htmlMatcher.find()) { String replacement = String.format("{%% asset_img %s %s %%}" , htmlMatcher.group(1 ), htmlMatcher.group(2 )); htmlMatcher.appendReplacement(sb, replacement); } htmlMatcher.appendTail(sb); String updatedContent = sb.toString(); sb.setLength(0 ); Pattern markdownPattern = Pattern.compile(redix2); Matcher markdownMatcher = markdownPattern.matcher(updatedContent); while (markdownMatcher.find()) { String replacement = String.format("{%% asset_img %s %s %%}" , markdownMatcher.group(2 ), markdownMatcher.group(1 )); markdownMatcher.appendReplacement(sb, replacement); } markdownMatcher.appendTail(sb); File outputFile = new File (outputDir, inputFile.getName()); try (BufferedWriter writer = new BufferedWriter (new FileWriter (outputFile))) { writer.write(sb.toString()); } System.out.println("Processed " + inputFile.getName()); } private static void copyRelatedFolder (File inputFile, File inputDir, File outputDir) throws IOException { String baseName = inputFile.getName().replaceAll("\\.md$" , "" ); File sourceFolder = new File (inputDir, baseName); File destinationFolder = new File (outputDir, baseName); if (sourceFolder.exists() && sourceFolder.isDirectory()) { copyDirectory(sourceFolder.toPath(), destinationFolder.toPath()); System.out.println("Copied folder " + baseName); } } private static void copyDirectory (Path source, Path target) throws IOException { Files.walkFileTree(source, new SimpleFileVisitor <Path>() { @Override public FileVisitResult preVisitDirectory (Path dir, BasicFileAttributes attrs) throws IOException { Path targetDir = target.resolve(source.relativize(dir)); try { Files.createDirectories(targetDir); } catch (FileAlreadyExistsException e) { if (!Files.isDirectory(targetDir)) throw e; } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile (Path file, BasicFileAttributes attrs) throws IOException { Files.copy(file, target.resolve(source.relativize(file)), StandardCopyOption.REPLACE_EXISTING); return FileVisitResult.CONTINUE; } }); } public static void addTheHexoBegin (String directoryPath) { String beginFilePath = "src/begin.txt" ; try { List<String> beginLines = Files.readAllLines(Paths.get(beginFilePath)); String beginContent = String.join(System.lineSeparator(), beginLines) + System.lineSeparator(); Files.list(Paths.get(directoryPath)) .filter(path -> path.toString().endsWith(".md" )) .forEach(path -> { try { List<String> lines = Files.readAllLines(path); if (lines.isEmpty() || !lines.get(0 ).trim().equals("---" )) { System.out.println("Updating file: " + path); addHeaderToFile(path, beginContent); }else { checkAndAddTitle(path, lines); checkAndAddDate(path, lines); } } catch (IOException e) { e.printStackTrace(); } }); } catch (IOException e) { e.printStackTrace(); } } private static void addHeaderToFile (Path filePath, String headerContent) throws IOException { List<String> originalLines = Files.readAllLines(filePath); String originalContent = String.join(System.lineSeparator(), originalLines); try (BufferedWriter writer = Files.newBufferedWriter(filePath)) { writer.write(headerContent); writer.write(originalContent); } } private static void checkAndAddTitle (Path filePath, List<String> lines) throws IOException { boolean titleFound = false ; boolean titleEmpty = false ; int titleIndex = -1 ; for (int i = 0 ; i < lines.size(); i++) { String line = lines.get(i).trim(); if (line.startsWith("title:" )) { titleFound = true ; if (line.equals("title:" ) || line.equals("title: " )) { titleEmpty = true ; titleIndex = i; } break ; } } if (titleFound && titleEmpty) { String fileName = filePath.getFileName().toString(); String baseName = fileName.substring(0 , fileName.lastIndexOf('.' )); lines.set(titleIndex, "title: " + baseName); try (BufferedWriter writer = Files.newBufferedWriter(filePath)) { for (String line : lines) { writer.write(line); writer.newLine(); } } System.out.println("Added file name to title in file: " + filePath); } } private static void checkAndAddDate (Path filePath, List<String> lines) throws IOException { boolean dateFound = false ; boolean dateEmpty = false ; int dateIndex = -1 ; for (int i = 0 ; i < lines.size(); i++) { String line = lines.get(i).trim(); if (line.startsWith("date:" )) { dateFound = true ; if (line.equals("date:" ) || line.equals("date: " )) { dateEmpty = true ; dateIndex = i; } break ; } } if (dateFound && dateEmpty) { String date = new SimpleDateFormat ("yyyy-MM-dd" ).format(new Date ()); lines.set(dateIndex, "date: " + date); try (BufferedWriter writer = Files.newBufferedWriter(filePath)) { for (String line : lines) { writer.write(line); writer.newLine(); } } System.out.println("Added file name to title in file: " + filePath); } } }
下面就是begin.txt的内容了
1 2 3 4 5 6 --- title: date: tags: [未分类] categories: [未分类] ---
下面的代码是用来删除加错的开头的,别问为啥有,问就是错了很多次。。。X﹏X
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import java.io.BufferedWriter;import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.util.List;public class MarkdownHeaderRemover { public static void main (String[] args) { String directoryPath = "A:\\usr\\MyBlog\\RawBlog" ; int linesToDelete = 6 ; try { Files.list(Paths.get(directoryPath)) .filter(path -> path.toString().endsWith(".md" )) .forEach(path -> { try { List<String> lines = Files.readAllLines(path); removeHeader(path, lines, linesToDelete); } catch (IOException e) { e.printStackTrace(); } }); } catch (IOException e) { e.printStackTrace(); } } private static void removeHeader (Path filePath, List<String> lines, int linesToDelete) throws IOException { int headerStartIndex = -1 ; for (int i = 0 ; i < lines.size(); i++) { if (lines.get(i).trim().equals("---" )) { headerStartIndex = i; break ; } } if (headerStartIndex != -1 && lines.size() > headerStartIndex + linesToDelete - 1 ) { lines.subList(headerStartIndex, headerStartIndex + linesToDelete).clear(); try (BufferedWriter writer = Files.newBufferedWriter(filePath)) { for (String line : lines) { writer.write(line); writer.newLine(); } } System.out.println("Removed header from file: " + filePath); } } }
然后记得备份!记得备份!记得备份!重要的说三次。里面的要删除行数变量 记得改 。
最后
处理过的就可以直接hexo g和hexo s看到图片了。