mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Add markdown support for task text in course creator and student plugins
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
<refactoring.moveHandler implementation="com.jetbrains.edu.coursecreator.handlers.CCTaskMoveHandlerDelegate" order="first"/>
|
||||
<renameHandler implementation="com.jetbrains.edu.coursecreator.handlers.CCTaskRenameHandler" order="first"/>
|
||||
<renameHandler implementation="com.jetbrains.edu.coursecreator.handlers.CCLessonRenameHandler" order="first"/>
|
||||
<applicationService serviceInterface="com.jetbrains.edu.coursecreator.settings.CCSettings"
|
||||
serviceImplementation="com.jetbrains.edu.coursecreator.settings.CCSettings"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="Edu">
|
||||
<studyActionsProvider implementation="com.jetbrains.edu.coursecreator.CCStudyActionsProvider"/>
|
||||
@@ -83,4 +85,8 @@
|
||||
<action id="UnpackCourse" class="com.jetbrains.edu.coursecreator.actions.CCFromCourseArchive"/>
|
||||
</actions>
|
||||
|
||||
<extensions defaultExtensionNs="Edu">
|
||||
<optionsProvider instance="com.jetbrains.edu.coursecreator.settings.CCOptions"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
+1
@@ -36,6 +36,7 @@ public class CCVirtualFileListener extends VirtualFileAdapter {
|
||||
String name = createdFile.getName();
|
||||
if (CCUtils.isTestsFile(project, createdFile)
|
||||
|| EduNames.TASK_HTML.equals(name)
|
||||
|| EduNames.TASK_MD.equals(name)
|
||||
|| name.contains(EduNames.WINDOW_POSTFIX)
|
||||
|| name.contains(EduNames.WINDOWS_POSTFIX)
|
||||
|| name.contains(EduNames.ANSWERS_POSTFIX)) {
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.Function;
|
||||
import com.jetbrains.edu.coursecreator.CCLanguageManager;
|
||||
import com.jetbrains.edu.coursecreator.CCUtils;
|
||||
import com.jetbrains.edu.coursecreator.settings.CCSettings;
|
||||
import com.jetbrains.edu.learning.core.EduNames;
|
||||
import com.jetbrains.edu.learning.core.EduUtils;
|
||||
import com.jetbrains.edu.learning.courseFormat.Course;
|
||||
@@ -99,7 +100,7 @@ public class CCCreateTask extends CCCreateStudyItemActionBase {
|
||||
return;
|
||||
}
|
||||
createFromTemplate(taskDirectory.get(), manager.getTestsTemplate(project), view, false);
|
||||
createFromTemplate(taskDirectory.get(), FileTemplateManager.getInstance(project).getInternalTemplate(EduNames.TASK_HTML), view, false);
|
||||
createFromTemplate(taskDirectory.get(), FileTemplateManager.getInstance(project).getInternalTemplate(CCSettings.getInstance().useHtmlAsDefaultTaskFormat() ? EduNames.TASK_HTML : EduNames.TASK_MD), view, false);
|
||||
String defaultExtension = manager.getDefaultTaskFileExtension();
|
||||
if (defaultExtension != null) {
|
||||
FileTemplate taskFileTemplate = manager.getTaskFileTemplateForExtension(project, defaultExtension);
|
||||
|
||||
+3
-1
@@ -10,6 +10,7 @@ import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.edu.coursecreator.CCUtils;
|
||||
import com.jetbrains.edu.coursecreator.settings.CCSettings;
|
||||
import com.jetbrains.edu.learning.StudyState;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
@@ -51,7 +52,8 @@ public class CCEditTaskTextAction extends ToggleAction implements DumbAware {
|
||||
return;
|
||||
}
|
||||
final StudyState studyState = new StudyState(selectedEditor);
|
||||
VirtualFile taskTextFile = studyState.getTaskDir().findChild(EduNames.TASK_HTML);
|
||||
VirtualFile taskTextFile = studyState.getTaskDir().findChild(CCSettings.getInstance().useHtmlAsDefaultTaskFormat() ?
|
||||
EduNames.TASK_HTML : EduNames.TASK_MD);
|
||||
if (taskTextFile == null) {
|
||||
LOG.info("Failed to find task.html");
|
||||
return;
|
||||
|
||||
+2
-1
@@ -42,7 +42,8 @@ public class CCTreeStructureProvider extends StudyTreeStructureProvider {
|
||||
if (virtualFile == null) {
|
||||
continue;
|
||||
}
|
||||
if (StudyUtils.getTaskFile(project, virtualFile) == null && !EduNames.TASK_HTML.equals(virtualFile.getName())) {
|
||||
if (StudyUtils.getTaskFile(project, virtualFile) == null && !EduNames.TASK_HTML.equals(virtualFile.getName())
|
||||
&& !EduNames.TASK_MD.equals(virtualFile.getName())) {
|
||||
modifiedChildren.add(new CCStudentInvisibleFileNode(project, ((PsiFileNode)node).getValue(), settings));
|
||||
}
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.coursecreator.settings.CCOptions">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="etched" title="Course creator">
|
||||
<font/>
|
||||
</border>
|
||||
<children>
|
||||
<grid id="2f67b" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="8c915" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Default task text format"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="3a318" class="javax.swing.JRadioButton" binding="myHtmlRadioButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="false"/>
|
||||
<text value="&Html"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="bf5e2" class="javax.swing.JRadioButton" binding="myMarkdownRadioButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="false"/>
|
||||
<text value="&Markdown"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<vspacer id="1926c">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
<buttonGroups>
|
||||
<group name="taskTextFormat">
|
||||
<member id="3a318"/>
|
||||
<member id="bf5e2"/>
|
||||
</group>
|
||||
</buttonGroups>
|
||||
</form>
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.jetbrains.edu.coursecreator.settings;
|
||||
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.jetbrains.edu.learning.settings.StudyOptionsProvider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class CCOptions implements StudyOptionsProvider {
|
||||
private JRadioButton myHtmlRadioButton;
|
||||
private JRadioButton myMarkdownRadioButton;
|
||||
private JPanel myPanel;
|
||||
private boolean myIsModified = false;
|
||||
|
||||
|
||||
public CCOptions() {
|
||||
myHtmlRadioButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myIsModified = true;
|
||||
}
|
||||
});
|
||||
|
||||
myMarkdownRadioButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myIsModified = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createComponent() {
|
||||
if (CCSettings.getInstance().useHtmlAsDefaultTaskFormat()) {
|
||||
myHtmlRadioButton.setSelected(true);
|
||||
myMarkdownRadioButton.setSelected(false);
|
||||
}
|
||||
else {
|
||||
myHtmlRadioButton.setSelected(false);
|
||||
myMarkdownRadioButton.setSelected(true);
|
||||
}
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myIsModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
if (myHtmlRadioButton.isSelected()) {
|
||||
CCSettings.getInstance().setUseHtmlAsDefaultTaskFormat(true);
|
||||
}
|
||||
else if (myMarkdownRadioButton.isSelected()) {
|
||||
CCSettings.getInstance().setUseHtmlAsDefaultTaskFormat(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.jetbrains.edu.coursecreator.settings;
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@State(name = "CCSettings", storages = @Storage("cc_settings.xml"))
|
||||
public class CCSettings implements PersistentStateComponent<CCSettings.State> {
|
||||
private CCSettings.State myState = new CCSettings.State();
|
||||
|
||||
public static class State {
|
||||
public boolean isHtmlDefault = true;
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public State getState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(State state) {
|
||||
myState = state;
|
||||
}
|
||||
|
||||
public boolean useHtmlAsDefaultTaskFormat() {
|
||||
return myState.isHtmlDefault;
|
||||
}
|
||||
|
||||
public void setUseHtmlAsDefaultTaskFormat(final boolean useHtml) {
|
||||
myState.isHtmlDefault = useHtml;
|
||||
}
|
||||
|
||||
public static CCSettings getInstance() {
|
||||
return ServiceManager.getService(CCSettings.class);
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,6 @@
|
||||
<refactoring.moveHandler implementation="com.jetbrains.edu.learning.StudyMoveDelegate" order="first"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="Edu">
|
||||
<optionsProvider instance="com.jetbrains.edu.learning.stepic.StepicOptionsProvider"/>
|
||||
<optionsProvider instance="com.jetbrains.edu.learning.stepic.StepicStudyOptions"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
@@ -35,6 +36,8 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.MarkdownUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.edu.learning.checker.StudyExecutor;
|
||||
import com.jetbrains.edu.learning.checker.StudyTestRunner;
|
||||
@@ -47,12 +50,14 @@ import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.ui.StudyProgressToolWindowFactory;
|
||||
import com.jetbrains.edu.learning.ui.StudyToolWindow;
|
||||
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
|
||||
import com.petebevin.markdown.MarkdownProcessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -389,7 +394,7 @@ public class StudyUtils {
|
||||
return false;
|
||||
}
|
||||
String name = virtualFile.getName();
|
||||
return !isTestsFile(project, name) && !EduNames.TASK_HTML.equals(name);
|
||||
return !isTestsFile(project, name) && !EduNames.TASK_HTML.equals(name) && !EduNames.TASK_MD.equals(name);
|
||||
}
|
||||
if (element instanceof PsiDirectory) {
|
||||
VirtualFile virtualFile = ((PsiDirectory)element).getVirtualFile();
|
||||
@@ -438,25 +443,35 @@ public class StudyUtils {
|
||||
return text;
|
||||
}
|
||||
if (taskDirectory != null) {
|
||||
VirtualFile taskTextFile = taskDirectory.findChild(EduNames.TASK_HTML);
|
||||
if (taskTextFile == null) {
|
||||
VirtualFile srcDir = taskDirectory.findChild("src");
|
||||
if (srcDir != null) {
|
||||
taskTextFile = srcDir.findChild(EduNames.TASK_HTML);
|
||||
}
|
||||
final String taskTextFileHtml = getTaskTextFrom(taskDirectory, EduNames.TASK_HTML);
|
||||
if (taskTextFileHtml != null) return taskTextFileHtml;
|
||||
|
||||
final String taskTextFileMd = getTaskTextFrom(taskDirectory, EduNames.TASK_MD);
|
||||
if (taskTextFileMd != null) return convertToHtml(taskTextFileMd);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getTaskTextFrom(@NotNull VirtualFile taskDirectory, @NotNull String taskTextFilename) {
|
||||
VirtualFile taskTextFile = taskDirectory.findChild(taskTextFilename);
|
||||
if (taskTextFile == null) {
|
||||
VirtualFile srcDir = taskDirectory.findChild("src");
|
||||
if (srcDir != null) {
|
||||
taskTextFile = srcDir.findChild(taskTextFilename);
|
||||
}
|
||||
if (taskTextFile != null) {
|
||||
try {
|
||||
return FileUtil.loadTextAndClose(taskTextFile.getInputStream());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
if (taskTextFile != null) {
|
||||
try {
|
||||
return FileUtil.loadTextAndClose(taskTextFile.getInputStream());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static StudyPluginConfigurator getConfigurator(@NotNull final Project project) {
|
||||
StudyPluginConfigurator[] extensions = StudyPluginConfigurator.EP_NAME.getExtensions();
|
||||
@@ -558,4 +573,12 @@ public class StudyUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String convertToHtml(@NotNull final String content) {
|
||||
ArrayList<String> lines = ContainerUtil.newArrayList(content.split("\n|\r|\r\n"));
|
||||
MarkdownUtil.replaceHeaders(lines);
|
||||
MarkdownUtil.replaceCodeBlock(lines);
|
||||
|
||||
return new MarkdownProcessor().markdown(StringUtil.join(lines, "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
@NonNls
|
||||
public class EduNames {
|
||||
public static final String TASK_HTML = "task.html";
|
||||
public static final String TASK_MD = "task.md";
|
||||
public static final String HINTS = "hints";
|
||||
public static final String LESSON = "lesson";
|
||||
public static final String LESSON_TITLED = StringUtil.toTitleCase(LESSON);
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ public class StudyGenerator {
|
||||
File resourceFile = new File(newResourceRoot, fileName);
|
||||
File fileInProject = new File(taskDir.getCanonicalPath(), fileName);
|
||||
FileUtil.copy(resourceFile, fileInProject);
|
||||
if (!StudyUtils.isTestsFile(project, fileName) && !EduNames.TASK_HTML.equals(fileName)) {
|
||||
if (!StudyUtils.isTestsFile(project, fileName) && !EduNames.TASK_HTML.equals(fileName) && !EduNames.TASK_MD.equals(fileName)) {
|
||||
StudyTaskManager.getInstance(project).addInvisibleFiles(FileUtil.toSystemIndependentName(fileInProject.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ public class StudyTreeStructureProvider implements TreeStructureProvider, DumbAw
|
||||
if (!StudyTaskManager.getInstance(project).isInvisibleFile(virtualFile.getPath())) {
|
||||
String fileName = virtualFile.getName();
|
||||
if (!fileName.contains(EduNames.WINDOW_POSTFIX) && !fileName.contains(EduNames.WINDOWS_POSTFIX)
|
||||
&& !StudyUtils.isTestsFile(project, fileName) && !EduNames.TASK_HTML.equals(fileName)) {
|
||||
&& !StudyUtils.isTestsFile(project, fileName) && !EduNames.TASK_HTML.equals(fileName) && !EduNames.TASK_MD.equals(fileName)) {
|
||||
nodes.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.jetbrains.edu.learning.stepic;
|
||||
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.jetbrains.edu.learning.settings.StudyOptionsProvider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class StepicOptionsProvider implements StudyOptionsProvider{
|
||||
|
||||
private StepicStudyOptions myPanel;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createComponent() {
|
||||
myPanel = new StepicStudyOptions();
|
||||
return myPanel.getPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myPanel.isModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
myPanel.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
myPanel.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
}
|
||||
}
|
||||
@@ -22,5 +22,6 @@
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module" module-name="xml" />
|
||||
<orderEntry type="library" name="markdownj" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
This is the markdown document.
|
||||
|
||||
Write your task text here
|
||||
Reference in New Issue
Block a user