All files / public/admin editorial-domain.js

96.05% Statements 73/76
88.88% Branches 80/90
92.85% Functions 13/14
95.94% Lines 71/74

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 15638x     38x 38x 38x 38x 38x 38x     168x       54x   54x       54x 54x       54x 1x   54x 11x   54x 1x   54x 2x   54x 2x     54x       19x       12x       9x       24x 24x   13x 24x       24x 24x 24x 24x   24x   24x 1x   24x 3x     24x 14x         10x           40x 3x       10x 2x   10x 2x   10x 2x   10x 1x   10x 2x 2x 2x 2x     10x 8x   10x       1x 1x   3x 3x 3x     1x       1x   5x     5x 5x       38x                    
(function (root) {
  "use strict";
 
  var POSTS_ROOT = "src/content/posts/";
  var MEDIA_ROOT = "public/images/posts/";
  var PUBLIC_POSTS_ROOT = "/posts/";
  var FORBIDDEN_TITLE_CHARACTERS = /[\\/:*?"<>|#%]/;
  var WINDOWS_RESERVED_NAME = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\..*)?$/i;
  var ARTICLE_MEDIA_PATTERN = /\/images\/posts\/[^\s)'"<>]+/g;
 
  function trimmedText(value) {
    return typeof value === "string" ? value.trim() : "";
  }
 
  function validateTitle(value) {
    var errors = [];
 
    Iif (typeof value !== "string" || !value) {
      return ["标题不能为空"];
    }
 
    var title = value.trim();
    Iif (!title) {
      return ["标题不能为空"];
    }
 
    if (value !== title) {
      errors.push("标题首尾不能包含空格");
    }
    if (FORBIDDEN_TITLE_CHARACTERS.test(title)) {
      errors.push('标题不能包含 \\ / : * ? " < > | # %');
    }
    if (title === "." || title === "..") {
      errors.push("标题不能是 . 或 ..");
    }
    if (/[. ]$/.test(title)) {
      errors.push("标题不能以句点或空格结尾");
    }
    if (WINDOWS_RESERVED_NAME.test(title)) {
      errors.push("标题不能使用 Windows 保留名称");
    }
 
    return errors;
  }
 
  function articlePath(title) {
    return POSTS_ROOT + trimmedText(title) + ".md";
  }
 
  function mediaFolder(title) {
    return MEDIA_ROOT + trimmedText(title);
  }
 
  function publicArticlePath(title) {
    return PUBLIC_POSTS_ROOT + trimmedText(title) + "/";
  }
 
  function isFutureDate(value) {
    var text = trimmedText(value);
    if (!text) return false;
 
    var date = new Date(text + (text.length === 10 ? "T00:00:00" : ""));
    return !Number.isNaN(date.getTime()) && date.getTime() > Date.now();
  }
 
  function validatePost(data) {
    var post = data || {};
    var errors = [];
    var warnings = [];
    var isDraft = post.draft === true;
 
    errors.push.apply(errors, validateTitle(post.title));
 
    if (post.featured === true && isDraft) {
      warnings.push("草稿被标记为精选,发布前请再次确认");
    }
    if (isFutureDate(post.publishedAt)) {
      warnings.push("发布日期在未来;当前后台不会自动定时发布");
    }
 
    if (isDraft) {
      return { errors: errors.filter(function (error) {
        return trimmedText(post.title) ? true : error !== "标题不能为空";
      }), warnings: warnings };
    }
 
    [
      ["title", "标题"],
      ["body", "正文"],
      ["category", "分类"],
      ["publishedAt", "发布日期"],
    ].forEach(function (field) {
      if (!trimmedText(post[field[0]])) {
        errors.push(field[1] + "不能为空");
      }
    });
 
    if (trimmedText(post.cover) && !trimmedText(post.coverAlt)) {
      errors.push("设置封面后必须填写封面替代文本");
    }
    if (/!\[\s*\]\([^)]+\)/.test(trimmedText(post.body))) {
      errors.push("正文图片必须填写替代文本后才能发布");
    }
    if (trimmedText(post.series) && (post.seriesOrder === undefined || post.seriesOrder === null || post.seriesOrder === "")) {
      errors.push("选择专题后必须填写专题顺序");
    }
    if (!trimmedText(post.series) && post.seriesOrder !== undefined && post.seriesOrder !== null && post.seriesOrder !== "") {
      errors.push("填写专题顺序前必须选择专题");
    }
    if (trimmedText(post.updatedAt) && trimmedText(post.publishedAt)) {
      var updated = new Date(post.updatedAt).getTime();
      var published = new Date(post.publishedAt).getTime();
      Eif (!Number.isNaN(updated) && !Number.isNaN(published) && updated < published) {
        errors.push("更新日期不能早于发布日期");
      }
    }
    if (!trimmedText(post.cover)) {
      warnings.push("文章尚未设置封面");
    }
    return { errors: errors, warnings: warnings };
  }
 
  function findMediaReferences(source) {
    var matches = String(source || "").match(ARTICLE_MEDIA_PATTERN) || [];
    var unique = [];
 
    matches.forEach(function (match) {
      var cleaned = match.replace(/[.,;:!?]+$/, "");
      if (unique.indexOf(cleaned) === -1) unique.push(cleaned);
    });
 
    return unique;
  }
 
  function countDraftEntries(entries) {
    return (Array.isArray(entries) ? entries : []).reduce(function (count, entry) {
      var source =
        (entry && typeof entry.data === "string" && entry.data) ||
        (entry && typeof entry.raw === "string" && entry.raw) ||
        "";
      var frontmatter = source.split("---", 3)[1] || "";
      return count + (/^draft:\s*true\s*$/m.test(frontmatter) ? 1 : 0);
    }, 0);
  }
 
  root.DecapEditorialDomain = {
    validateTitle: validateTitle,
    articlePath: articlePath,
    mediaFolder: mediaFolder,
    publicArticlePath: publicArticlePath,
    validatePost: validatePost,
    findMediaReferences: findMediaReferences,
    countDraftEntries: countDraftEntries,
  };
})(typeof window !== "undefined" ? window : globalThis);