diff options
Diffstat (limited to 'app/assets/javascripts/static_site_editor/services')
4 files changed, 93 insertions, 17 deletions
diff --git a/app/assets/javascripts/static_site_editor/services/front_matterify.js b/app/assets/javascripts/static_site_editor/services/front_matterify.js new file mode 100644 index 00000000000..cbf0fffd515 --- /dev/null +++ b/app/assets/javascripts/static_site_editor/services/front_matterify.js @@ -0,0 +1,73 @@ +import jsYaml from 'js-yaml'; + +const NEW_LINE = '\n'; + +const hasMatter = (firstThreeChars, fourthChar) => { + const isYamlDelimiter = firstThreeChars === '---'; + const isFourthCharNewline = fourthChar === NEW_LINE; + return isYamlDelimiter && isFourthCharNewline; +}; + +export const frontMatterify = source => { + let index = 3; + let offset; + const delimiter = source.slice(0, index); + const type = 'yaml'; + const NO_FRONTMATTER = { + source, + matter: null, + spacing: null, + content: source, + delimiter: null, + type: null, + }; + + if (!hasMatter(delimiter, source.charAt(index))) { + return NO_FRONTMATTER; + } + + offset = source.indexOf(delimiter, index); + + // Finds the end delimiter that starts at a new line + while (offset !== -1 && source.charAt(offset - 1) !== NEW_LINE) { + index = offset + delimiter.length; + offset = source.indexOf(delimiter, index); + } + + if (offset === -1) { + return NO_FRONTMATTER; + } + + const matterStr = source.slice(index, offset); + const matter = jsYaml.safeLoad(matterStr); + + let content = source.slice(offset + delimiter.length); + let spacing = ''; + let idx = 0; + while (content.charAt(idx).match(/(\s|\n)/)) { + spacing += content.charAt(idx); + idx += 1; + } + content = content.replace(spacing, ''); + + return { + source, + matter, + spacing, + content, + delimiter, + type, + }; +}; + +export const stringify = ({ matter, spacing, content, delimiter }, newMatter) => { + const matterObj = newMatter || matter; + + if (!matterObj) { + return content; + } + + const header = `${delimiter}${NEW_LINE}${jsYaml.safeDump(matterObj)}${delimiter}`; + const body = `${spacing}${content}`; + return `${header}${body}`; +}; diff --git a/app/assets/javascripts/static_site_editor/services/parse_source_file.js b/app/assets/javascripts/static_site_editor/services/parse_source_file.js index 640186ee1d0..d4fc8b2edb6 100644 --- a/app/assets/javascripts/static_site_editor/services/parse_source_file.js +++ b/app/assets/javascripts/static_site_editor/services/parse_source_file.js @@ -1,7 +1,7 @@ -import grayMatter from 'gray-matter'; +import { frontMatterify, stringify } from './front_matterify'; const parseSourceFile = raw => { - const remake = source => grayMatter(source, {}); + const remake = source => frontMatterify(source); let editable = remake(raw); @@ -13,20 +13,17 @@ const parseSourceFile = raw => { } }; - const trimmedEditable = () => grayMatter.stringify(editable).trim(); + const content = (isBody = false) => (isBody ? editable.content : stringify(editable)); - const content = (isBody = false) => (isBody ? editable.content.trim() : trimmedEditable()); // gray-matter internally adds an eof newline so we trim to bypass, open issue: https://github.com/jonschlinkert/gray-matter/issues/96 - - const matter = () => editable.data; + const matter = () => editable.matter; const syncMatter = settings => { - const source = grayMatter.stringify(editable.content, settings); - syncContent(source); + editable.matter = settings; }; - const isModified = () => trimmedEditable() !== raw; + const isModified = () => stringify(editable) !== raw; - const hasMatter = () => editable.matter.length > 0; + const hasMatter = () => Boolean(editable.matter); return { matter, diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js index da62d3fa4fc..8623a671a7d 100644 --- a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js +++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js @@ -1,6 +1,5 @@ import Api from '~/api'; import Tracking from '~/tracking'; -import { s__, sprintf } from '~/locale'; import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils'; import generateBranchName from '~/static_site_editor/services/generate_branch_name'; @@ -71,6 +70,7 @@ const commitContent = (projectId, message, branch, sourcePath, content, images) const createMergeRequest = ( projectId, title, + description, sourceBranch, targetBranch = DEFAULT_TARGET_BRANCH, ) => { @@ -80,6 +80,7 @@ const createMergeRequest = ( projectId, convertObjectPropsToSnakeCase({ title, + description, sourceBranch, targetBranch, }), @@ -88,11 +89,16 @@ const createMergeRequest = ( }); }; -const submitContentChanges = ({ username, projectId, sourcePath, content, images }) => { +const submitContentChanges = ({ + username, + projectId, + sourcePath, + content, + images, + mergeRequestMeta, +}) => { const branch = generateBranchName(username); - const mergeRequestTitle = sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), { - sourcePath, - }); + const { title: mergeRequestTitle, description: mergeRequestDescription } = mergeRequestMeta; const meta = {}; return createBranch(projectId, branch) @@ -104,7 +110,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content, images .then(({ data: { short_id: label, web_url: url } }) => { Object.assign(meta, { commit: { label, url } }); - return createMergeRequest(projectId, mergeRequestTitle, branch); + return createMergeRequest(projectId, mergeRequestTitle, mergeRequestDescription, branch); }) .then(({ data: { iid: label, web_url: url } }) => { Object.assign(meta, { mergeRequest: { label: label.toString(), url } }); diff --git a/app/assets/javascripts/static_site_editor/services/templater.js b/app/assets/javascripts/static_site_editor/services/templater.js index a1c1bb6b8d6..d302aea78a3 100644 --- a/app/assets/javascripts/static_site_editor/services/templater.js +++ b/app/assets/javascripts/static_site_editor/services/templater.js @@ -15,7 +15,7 @@ const markPrefix = `${marker}-${Date.now()}`; const reHelpers = { template: `.| |\\t|\\n(?!(\\n|${markPrefix}))`, - openTag: '<[a-zA-Z]+.*?>', + openTag: '<(?!figure|iframe)[a-zA-Z]+.*?>', closeTag: '</.+>', }; const reTemplated = new RegExp(`(^${wrapPrefix}(${reHelpers.template})+?${wrapPostfix}$)`, 'gm'); |