/*
* YamlFrontMatter.java
*
* Copyright (C) 2009-14 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.studio.client.rmarkdown.model;
import org.rstudio.studio.client.workbench.views.source.editors.text.DocDisplay;
import org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position;
import org.rstudio.studio.client.workbench.views.source.editors.text.ace.Range;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
public class YamlFrontMatter
{
public static Range getFrontMatterRange(DocDisplay display)
{
// front matter can end with ... rather than ---; see spec:
// http://www.yaml.org/spec/1.2/spec.html#id2760395
RegExp frontMatterBegin = RegExp.compile("^---\\s*$", "gm");
RegExp frontMatterEnd = RegExp.compile("^(---|\\.\\.\\.)\\s*$", "gm");
Position begin = null;
Position end = null;
for (int i = 0; i < display.getRowCount(); i++)
{
String code = display.getLine(i);
if (begin == null)
{
// haven't found front matter begin yet; test this line
MatchResult beginMatch = frontMatterBegin.exec(code);
if (beginMatch == null)
{
// ensure that only whitespace exists before the beginning ---
// (this matches front matter extraction behavior in the R
// Markdown package)
if (!code.matches("\\s*"))
break;
}
else
{
begin = Position.create(i + 1, 0);
continue;
}
}
else if (end == null)
{
// haven't found front matter end yet; test this line
MatchResult endMatch = frontMatterEnd.exec(code);
if (endMatch != null)
{
end = Position.create(i, 0);
break;
}
}
}
if (begin == null || end == null)
return null;
return Range.fromPoints(begin, end);
}
public static String getFrontMatter(DocDisplay display)
{
Range range = getFrontMatterRange(display);
if (range == null)
{
return "output: html_document\n";
}
else
{
return display.getTextForRange(range);
}
}
/**
* Replaces the document's front matter with the given front matter;
* adds a new front matter section if none exists.
*
* @param display The editor to mutate
* @param yaml The new front matter
* @return Whether the editor buffer was mutated
*/
public static boolean applyFrontMatter(DocDisplay display, String yaml)
{
if (yaml == null || yaml.isEmpty())
return false;
Range range = YamlFrontMatter.getFrontMatterRange(display);
if (range == null)
{
// add the YAML if no front matter exists
range = Range.create(0, 0, 0, 0);
yaml = RmdFrontMatter.FRONTMATTER_SEPARATOR +
yaml +
RmdFrontMatter.FRONTMATTER_SEPARATOR;
}
else if (display.getTextForRange(range) == yaml)
{
return false;
}
display.replaceRange(range, yaml);
return true;
}
}