under construction
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("elex-springboot")
|
||||
id("org.springframework.boot") version "2.4.2"
|
||||
|
||||
id("org.springframework.boot") version "2.5.3"
|
||||
id("io.spring.dependency-management") version "1.0.11.RELEASE"
|
||||
id("org.asciidoctor.convert") version "1.5.8"
|
||||
}
|
||||
@@ -9,6 +17,12 @@ group = "com.elex-project"
|
||||
version = "0.0.1-SNAPSHOT"
|
||||
description = ""
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("https://repository.elex-project.com/repository/maven")
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
set("snippetsDir", file("build/generated-snippets"))
|
||||
}
|
||||
@@ -25,9 +39,17 @@ tasks.asciidoctor {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-mustache")
|
||||
implementation(project(":sitemap"))
|
||||
implementation(project(":linkback"))
|
||||
|
||||
implementation(project(":address-finder"))
|
||||
implementation("com.vladsch.flexmark:flexmark-all:0.62.2")
|
||||
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
|
||||
|
||||
//implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.boot:spring-boot-starter-cache")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
|
||||
//implementation ("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
|
||||
@@ -36,6 +58,7 @@ dependencies {
|
||||
compileOnly("org.projectlombok:lombok")
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||
//runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
|
||||
runtimeOnly("com.h2database:h2")
|
||||
|
||||
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
||||
annotationProcessor("org.projectlombok:lombok")
|
||||
|
||||
34
app/src/main/java/com/elex_project/asgard/Application.java
Normal file
34
app/src/main/java/com/elex_project/asgard/Application.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@EnableCaching
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@Component
|
||||
static class Runner implements CommandLineRunner {
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
54
app/src/main/java/com/elex_project/asgard/config/Config.java
Normal file
54
app/src/main/java/com/elex_project/asgard/config/Config.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.config;
|
||||
|
||||
import com.elex_project.asgard.supplements.Markdown;
|
||||
import com.elex_project.asgard.view.AsgardLocaleResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
|
||||
@Configuration
|
||||
public class Config {
|
||||
|
||||
/*@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
*/
|
||||
/*@Bean
|
||||
public HttpTraceRepository httpTraceRepository() {
|
||||
return new InMemoryHttpTraceRepository();
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* Locale resolver, 디폴트 로캐일을 지정한다.
|
||||
*/
|
||||
@Bean
|
||||
public LocaleResolver localeResolver() {
|
||||
/*SessionLocaleResolver localeResolver = new SessionLocaleResolver();
|
||||
localeResolver.setDefaultLocale(Locale.ENGLISH);
|
||||
localeResolver.setLocaleAttributeName("lc");
|
||||
localeResolver.setTimeZoneAttributeName("tz");
|
||||
return localeResolver;*/
|
||||
|
||||
return new AsgardLocaleResolver();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Markdown parser
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Markdown markdown() {
|
||||
return new Markdown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.config;
|
||||
|
||||
import com.elex_project.asgard.view.AsgardLocaleChangeInterceptor;
|
||||
import com.elex_project.asgard.view.ViewModelInterceptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class ViewConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(@NotNull InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new AsgardLocaleChangeInterceptor())
|
||||
.addPathPatterns("/**");
|
||||
|
||||
registry.addInterceptor(new ViewModelInterceptor())
|
||||
.addPathPatterns("/**");
|
||||
|
||||
/*registry.addInterceptor(new RequestLogInterceptor())
|
||||
.addPathPatterns("/**");*/
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.config;
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.controller;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
abstract class BaseController {
|
||||
|
||||
/*@NotNull
|
||||
protected Map<String, Object> map() {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("html_lang", lang());
|
||||
return map;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String lang() {
|
||||
return getHttpRequest()
|
||||
.map(request -> request.getLocale().toLanguageTag())
|
||||
.orElse("en");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected URI getRequestURI() {
|
||||
return getHttpRequest()
|
||||
.map(request -> URI.create(request.getRequestURI()))
|
||||
.orElse(URI.create("/"));
|
||||
}
|
||||
|
||||
private Optional<ServletRequestAttributes> getRequestAttributes() {
|
||||
return Optional
|
||||
.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
|
||||
}
|
||||
|
||||
protected Optional<HttpServletRequest> getHttpRequest() {
|
||||
return getRequestAttributes()
|
||||
.map(ServletRequestAttributes::getRequest);
|
||||
}
|
||||
|
||||
protected Optional<HttpServletResponse> getHttpResponse() {
|
||||
return getRequestAttributes()
|
||||
.map(ServletRequestAttributes::getResponse);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String[] getAttributeNames() {
|
||||
return getRequestAttributes()
|
||||
.map(attr -> attr.getAttributeNames(RequestAttributes.SCOPE_REQUEST))
|
||||
.orElse(new String[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String[] getSessionAttributeNames() {
|
||||
return getRequestAttributes()
|
||||
.map(attr -> attr.getAttributeNames(RequestAttributes.SCOPE_SESSION))
|
||||
.orElse(new String[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Optional<Object> getAttribute(@NotNull final String key) {
|
||||
return getRequestAttributes()
|
||||
.map(attr -> attr.getAttribute(key, RequestAttributes.SCOPE_REQUEST));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Optional<Object> getSessionAttribute(@NotNull final String key) {
|
||||
return getRequestAttributes()
|
||||
.map(attr -> attr.getAttribute(key, RequestAttributes.SCOPE_SESSION));
|
||||
}
|
||||
|
||||
protected void setAttribute(@NotNull final String key, final Object value) {
|
||||
getRequestAttributes()
|
||||
.ifPresent(attr -> attr.setAttribute(key, value, RequestAttributes.SCOPE_REQUEST));
|
||||
}
|
||||
|
||||
protected void setSessionAttribute(@NotNull final String key, final Object value) {
|
||||
getRequestAttributes()
|
||||
.ifPresent(attr -> attr.setAttribute(key, value, RequestAttributes.SCOPE_SESSION));
|
||||
}
|
||||
|
||||
protected void removeAttribute(@NotNull final String key) {
|
||||
getRequestAttributes()
|
||||
.ifPresent(attr -> attr.removeAttribute(key, RequestAttributes.SCOPE_REQUEST));
|
||||
}
|
||||
|
||||
protected void removeSessionAttribute(@NotNull final String key) {
|
||||
getRequestAttributes()
|
||||
.ifPresent(attr -> attr.removeAttribute(key, RequestAttributes.SCOPE_SESSION));
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.controller;
|
||||
|
||||
import com.elex_project.asgard.service.SitemapService;
|
||||
import com.elex_project.asgard.service.SyndicationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @link http://www.robotstxt.org/robotstxt.html
|
||||
* @link http://humanstxt.org/
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
public class HomeController extends BaseController {
|
||||
@Autowired
|
||||
private SyndicationService syndicationService;
|
||||
@Autowired
|
||||
private SitemapService sitemapService;
|
||||
|
||||
@GetMapping(path = "/exception")
|
||||
public void ex() throws Exception {
|
||||
throw new Exception("Test Exception");
|
||||
}
|
||||
|
||||
@GetMapping(path = "/exception2")
|
||||
public void ex2() throws ResponseStatusException {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Test Exception");
|
||||
}
|
||||
|
||||
@GetMapping(path = "/")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public String home(Model model) {
|
||||
|
||||
//final Map<String, Object> map = map();
|
||||
//map.put("title", "Title~!");
|
||||
return "home";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @link {https://www.sitemaps.org/ko/protocol.html}
|
||||
*/
|
||||
@GetMapping(path = "/sitemap.xml",
|
||||
produces = {MediaType.APPLICATION_XML_VALUE})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ResponseBody
|
||||
public String sitemap() {
|
||||
return sitemapService.getSitemap();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @link {https://validator.w3.org/feed/docs/rss2.html}
|
||||
*/
|
||||
@GetMapping(path = "/rss.xml",
|
||||
produces = {MediaType.APPLICATION_RSS_XML_VALUE})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ResponseBody
|
||||
public String rss() {
|
||||
return syndicationService.getRssSyndication();
|
||||
//return "syndication/rss2";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @link {https://validator.w3.org/feed/docs/atom.html}
|
||||
*/
|
||||
@GetMapping(path = "/atom.xml",
|
||||
produces = {MediaType.APPLICATION_ATOM_XML_VALUE})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ResponseBody
|
||||
public String atom() {
|
||||
return syndicationService.getAtomSyndication();
|
||||
}
|
||||
|
||||
@PostMapping(path = "/trackback/{id}",
|
||||
produces = {MediaType.APPLICATION_XML_VALUE})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ModelAndView trackback(@PathVariable String id) {
|
||||
return new ModelAndView();
|
||||
}
|
||||
|
||||
@PostMapping(path = "/pingback",
|
||||
produces = {MediaType.APPLICATION_XML_VALUE})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ModelAndView pingback(@RequestParam String source, @RequestParam String target) {
|
||||
return new ModelAndView();
|
||||
}
|
||||
|
||||
@PostMapping(path = "/webmention",
|
||||
produces = {MediaType.APPLICATION_XML_VALUE})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ModelAndView webmention(@RequestParam String source, @RequestParam String target) {
|
||||
return new ModelAndView();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.controller;
|
||||
|
||||
import com.elex_project.asgard.service.NoteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
public class NoteController extends BaseController {
|
||||
@Autowired
|
||||
private NoteService noteService;
|
||||
|
||||
/*@GetMapping(path = "/*")
|
||||
public ModelAndView reader(){
|
||||
|
||||
return new ModelAndView("document", map());
|
||||
}*/
|
||||
@GetMapping(path = "/*")
|
||||
public ModelAndView editor(@RequestParam boolean edit, ModelAndView model) {
|
||||
if (edit) {
|
||||
model.setViewName("edit");
|
||||
} else {
|
||||
model.setViewName("document");
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
@PostMapping(path = "/*")
|
||||
public ResponseEntity<String> update(@RequestBody String p) {
|
||||
return ResponseEntity.created(URI.create("")).build();
|
||||
//todo redirect -> get
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/*")
|
||||
public ResponseEntity<String> delete() {
|
||||
return ResponseEntity.ok().build();
|
||||
//todo redirect -> get
|
||||
}
|
||||
|
||||
@PostMapping()
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public String uploadFile(final @RequestParam("file") MultipartFile file,
|
||||
final @NotNull RedirectAttributes redirectAttributes) {
|
||||
//storageService.store(file);
|
||||
|
||||
// 업로드 후 새로 고침
|
||||
redirectAttributes.addFlashAttribute("message",
|
||||
"You successfully uploaded " + file.getOriginalFilename() + "!");
|
||||
return "redirect:/";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.controller;
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.model;
|
||||
|
||||
import com.elex_project.asgard.supplements.InetAddressConverter;
|
||||
import com.elex_project.asgard.supplements.StringArrayConverter;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.elex_project.asgard.supplements.RequestLogInterceptor.REQUEST_TIME;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "http_trace")
|
||||
public class HttpTraceModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
@Column
|
||||
private LocalDateTime requestTime;
|
||||
@Column
|
||||
private Long elapsed;
|
||||
@Column
|
||||
private String requestUrl;
|
||||
@Column
|
||||
private String requestMethod;
|
||||
@Column
|
||||
private String userAgent;
|
||||
@Column
|
||||
private String referer;
|
||||
@Column
|
||||
@Convert(converter = StringArrayConverter.class)
|
||||
private String[] acceptLang;
|
||||
@Column
|
||||
@Convert(converter = InetAddressConverter.class)
|
||||
private InetAddress ipAddress;
|
||||
|
||||
public static HttpTraceModel of(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
final HttpTraceModel model = new HttpTraceModel();
|
||||
model.requestUrl = request.getRequestURI();
|
||||
model.requestMethod = request.getMethod();
|
||||
model.userAgent = request.getHeader("User-Agent");
|
||||
model.referer = request.getHeader("Referer");
|
||||
|
||||
final String acceptLang = request.getHeader("Accept-Language");
|
||||
if (null != acceptLang) {
|
||||
model.acceptLang = acceptLang.replaceAll(";q=[0-9.]*", "").split(",");
|
||||
} else {
|
||||
model.acceptLang = new String[0];
|
||||
}
|
||||
|
||||
model.requestTime = (LocalDateTime) request.getAttribute(REQUEST_TIME);
|
||||
if (null != model.requestTime) {
|
||||
model.elapsed = Duration.between(model.requestTime, LocalDateTime.now()).toMillis();
|
||||
}
|
||||
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
if (null == ip) ip = request.getHeader("X-Real-Ip");
|
||||
if (null == ip) ip = request.getRemoteAddr();
|
||||
try {
|
||||
model.ipAddress = InetAddress.getByName(ip);
|
||||
} catch (UnknownHostException ignore) {
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
||||
54
app/src/main/java/com/elex_project/asgard/model/Note.java
Normal file
54
app/src/main/java/com/elex_project/asgard/model/Note.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.model;
|
||||
|
||||
import com.elex_project.asgard.supplements.StringArrayConverter;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "notes")
|
||||
public class Note {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
@Column(unique = true, nullable = false)
|
||||
private String url;
|
||||
@Column
|
||||
private String title;
|
||||
@Column
|
||||
private String description;
|
||||
@Column
|
||||
@Convert(converter = StringArrayConverter.class)
|
||||
private String[] tags;
|
||||
@Column
|
||||
private boolean published;
|
||||
@Column
|
||||
private String content;
|
||||
@Column
|
||||
private String markdownContent;
|
||||
@Column
|
||||
@CreatedDate
|
||||
private LocalDateTime createdOn;
|
||||
@Column
|
||||
@LastModifiedDate
|
||||
private LocalDateTime modifiedOn;
|
||||
|
||||
public static Note of(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.model;
|
||||
|
||||
public class Pingback {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.model;
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard;
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class NoteService {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PingbackService {
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.service;
|
||||
|
||||
import com.elex_project.asgard.sitemap.BaseSitemapService;
|
||||
import com.elex_project.asgard.sitemap.Frequency;
|
||||
import com.elex_project.asgard.sitemap.Sitemap;
|
||||
import com.elex_project.asgard.sitemap.SitemapItem;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "sitemap")
|
||||
public class SitemapService extends BaseSitemapService {
|
||||
|
||||
@Override
|
||||
protected Sitemap sitemap() {
|
||||
final Sitemap sitemap = new Sitemap();
|
||||
sitemap.addItem(SitemapItem.builder()
|
||||
.loc("https://aaa.com/1")
|
||||
.lastMod(LocalDateTime.now())
|
||||
.changeFreq(Frequency.HOURLY)
|
||||
.build());
|
||||
sitemap.addItem(SitemapItem.builder()
|
||||
.loc("https://aaa.com/2")
|
||||
.lastMod(LocalDateTime.now())
|
||||
.build());// todo
|
||||
return sitemap;
|
||||
}
|
||||
|
||||
//@CacheEvict(allEntries = true)
|
||||
public void clearCaches() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.service;
|
||||
|
||||
import com.elex_project.asgard.syndication.BaseSyndicationService;
|
||||
import com.elex_project.asgard.syndication.Syndication;
|
||||
import com.elex_project.asgard.syndication.SyndicationItem;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
//@CacheConfig(cacheNames = "templates/syndication")
|
||||
public class SyndicationService extends BaseSyndicationService {
|
||||
|
||||
|
||||
//@CacheEvict(allEntries = true)
|
||||
public void clearCaches() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Syndication syndication() {
|
||||
final Syndication syndication = Syndication.builder()
|
||||
.title("Elex Project")
|
||||
.link("https://www.elex-project.com/")
|
||||
.linkAtom("https://www.elex-project.com/atom")
|
||||
.linkRss("https://www.elex-project.com/rss")
|
||||
.description("Sample description")
|
||||
.language(Locale.KOREAN)
|
||||
.copyright("Copyright (c) 2021 Elex. All Rights Reserved.")
|
||||
.imageUrl("https://www.elex-project.com/images/logo.png")
|
||||
.lastBuildDate(LocalDateTime.now())
|
||||
.item(SyndicationItem.builder()
|
||||
.authorName("Elex")
|
||||
.authorEmail("email@example.com")
|
||||
.description("Sample article")
|
||||
.modDate(LocalDateTime.now())
|
||||
.pubDate(LocalDateTime.now())
|
||||
.title("Sample title")
|
||||
.url("https://something.com/1")
|
||||
.build())
|
||||
.item(SyndicationItem.builder()
|
||||
.authorName("Elex")
|
||||
.authorEmail("email@example.com")
|
||||
.description("Sample article 2")
|
||||
.modDate(LocalDateTime.now())
|
||||
.pubDate(LocalDateTime.now())
|
||||
.title("Sample title 2")
|
||||
.url("https://something.com/2")
|
||||
.build())
|
||||
.build();
|
||||
final List<SyndicationItem> items = new ArrayList<>();// todo
|
||||
items.forEach(syndication::addItem);
|
||||
return syndication;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TrackbackService {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.service;
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.supplements;
|
||||
|
||||
import com.elex_project.abraxas.Stringz;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@Converter
|
||||
@Slf4j
|
||||
public class InetAddressConverter implements AttributeConverter<InetAddress, byte[]> {
|
||||
private static final InetAddress NULL_IP;
|
||||
|
||||
static {
|
||||
try {
|
||||
NULL_IP = InetAddress.getByAddress(new byte[]{0, 0, 0, 0});
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException("Unable to make a Null-Ip.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertToDatabaseColumn(final InetAddress attribute) {
|
||||
return attribute.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress convertToEntityAttribute(final byte[] dbData) {
|
||||
try {
|
||||
return InetAddress.getByAddress(dbData);
|
||||
} catch (UnknownHostException e) {
|
||||
log.warn("Unable to convert IP address of {}", Stringz.fromBytes(dbData));
|
||||
return NULL_IP;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.supplements;
|
||||
|
||||
import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension;
|
||||
import com.vladsch.flexmark.ext.aside.AsideExtension;
|
||||
import com.vladsch.flexmark.ext.autolink.AutolinkExtension;
|
||||
import com.vladsch.flexmark.ext.definition.DefinitionExtension;
|
||||
import com.vladsch.flexmark.ext.footnotes.FootnoteExtension;
|
||||
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughSubscriptExtension;
|
||||
import com.vladsch.flexmark.ext.ins.InsExtension;
|
||||
import com.vladsch.flexmark.ext.media.tags.MediaTagsExtension;
|
||||
import com.vladsch.flexmark.ext.superscript.SuperscriptExtension;
|
||||
import com.vladsch.flexmark.ext.tables.TablesExtension;
|
||||
import com.vladsch.flexmark.ext.typographic.TypographicExtension;
|
||||
import com.vladsch.flexmark.ext.yaml.front.matter.AbstractYamlFrontMatterVisitor;
|
||||
import com.vladsch.flexmark.ext.yaml.front.matter.YamlFrontMatterExtension;
|
||||
import com.vladsch.flexmark.ext.youtube.embedded.YouTubeLinkExtension;
|
||||
import com.vladsch.flexmark.html.HtmlRenderer;
|
||||
import com.vladsch.flexmark.parser.Parser;
|
||||
import com.vladsch.flexmark.util.ast.KeepType;
|
||||
import com.vladsch.flexmark.util.ast.Node;
|
||||
import com.vladsch.flexmark.util.data.DataHolder;
|
||||
import com.vladsch.flexmark.util.data.MutableDataSet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Markdown {
|
||||
/**
|
||||
* Flexmark Options
|
||||
*
|
||||
* @link {https://github.com/vsch/flexmark-java/wiki/Extensions}
|
||||
*/
|
||||
private static final DataHolder OPTIONS = new MutableDataSet()
|
||||
.set(Parser.REFERENCES_KEEP, KeepType.LAST)
|
||||
.set(HtmlRenderer.INDENT_SIZE, 2)
|
||||
.set(HtmlRenderer.PERCENT_ENCODE_URLS, true)
|
||||
|
||||
// for full GFM table compatibility add the following table extension options:
|
||||
.set(TablesExtension.COLUMN_SPANS, false)
|
||||
.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
|
||||
.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
|
||||
.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
|
||||
.set(Parser.EXTENSIONS, Arrays.asList(
|
||||
AnchorLinkExtension.create(),
|
||||
AsideExtension.create(),
|
||||
AutolinkExtension.create(),
|
||||
DefinitionExtension.create(),
|
||||
FootnoteExtension.create(),
|
||||
StrikethroughSubscriptExtension.create(),
|
||||
InsExtension.create(),
|
||||
MediaTagsExtension.create(),
|
||||
SuperscriptExtension.create(),
|
||||
TablesExtension.create(),
|
||||
TypographicExtension.create(),
|
||||
YamlFrontMatterExtension.create(),
|
||||
YouTubeLinkExtension.create()
|
||||
))
|
||||
.toImmutable();
|
||||
|
||||
private final Parser parser;
|
||||
private final HtmlRenderer renderer;
|
||||
|
||||
public Markdown() {
|
||||
this.parser = Parser.builder(OPTIONS).build();
|
||||
this.renderer = HtmlRenderer.builder(OPTIONS).build();
|
||||
}
|
||||
|
||||
public Node parse(final String md) {
|
||||
return parser.parse(md);
|
||||
}
|
||||
|
||||
public Node parse(final InputStream md) throws IOException {
|
||||
return parse(new InputStreamReader(md));
|
||||
}
|
||||
|
||||
public Node parse(final Reader md) throws IOException {
|
||||
return parser.parseReader(md);
|
||||
}
|
||||
|
||||
public String render(final String md) {
|
||||
return renderer.render(parse(md));
|
||||
}
|
||||
|
||||
public String render(final Node md) {
|
||||
return renderer.render(md);
|
||||
}
|
||||
|
||||
public Map<String, List<String>> frontMatter(final Node md) {
|
||||
AbstractYamlFrontMatterVisitor visitor = new AbstractYamlFrontMatterVisitor();
|
||||
visitor.visit(md);
|
||||
return visitor.getData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.supplements;
|
||||
|
||||
import com.elex_project.asgard.model.HttpTraceModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
public class RequestLogInterceptor implements HandlerInterceptor {
|
||||
public static final String REQUEST_TIME = "elex.request.time";
|
||||
|
||||
@Override
|
||||
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler)
|
||||
throws Exception {
|
||||
request.setAttribute(REQUEST_TIME, LocalDateTime.now());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView)
|
||||
throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex)
|
||||
throws Exception {
|
||||
final HttpTraceModel traceModel = HttpTraceModel.of(request, response);
|
||||
log.info("Http Trace: {}", traceModel);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.supplements;
|
||||
|
||||
import com.elex_project.abraxas.Stringz;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
@Converter
|
||||
public class StringArrayConverter implements AttributeConverter<String[], String> {
|
||||
@Override
|
||||
public String convertToDatabaseColumn(final String[] attribute) {
|
||||
return Stringz.join(',', attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] convertToEntityAttribute(final String dbData) {
|
||||
return dbData.split(",");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.supplements;
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.view;
|
||||
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
|
||||
import static com.elex_project.asgard.view.AsgardLocaleResolver.PARAM;
|
||||
|
||||
public class AsgardLocaleChangeInterceptor extends LocaleChangeInterceptor {
|
||||
|
||||
public AsgardLocaleChangeInterceptor() {
|
||||
this.setParamName(PARAM);
|
||||
this.setIgnoreInvalidLocale(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.view;
|
||||
|
||||
import com.elex_project.abraxas.I18n;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 로케일 리졸버
|
||||
* AcceptHeaderLocaleResolver를 기본 정책으로하되, GET 파라미터로 로캐일 변환이 가능하도록 한다.
|
||||
*
|
||||
* @author Elex
|
||||
*/
|
||||
@Slf4j
|
||||
public class AsgardLocaleResolver implements LocaleResolver {
|
||||
@Value("asgard.locale.param:lang")
|
||||
static String PARAM;
|
||||
|
||||
/**
|
||||
* 지원되는 로캐일 목록. 첫 번째 로캐일은 기본 로캐일로 사용된다.
|
||||
*/
|
||||
private static final List<Locale> supportedLocales = List
|
||||
.of(Locale.KOREAN, Locale.ENGLISH);
|
||||
|
||||
private final AcceptHeaderLocaleResolver acceptHeaderLocaleResolver;
|
||||
|
||||
public AsgardLocaleResolver() {
|
||||
acceptHeaderLocaleResolver = new AcceptHeaderLocaleResolver();
|
||||
acceptHeaderLocaleResolver.setSupportedLocales(supportedLocales);
|
||||
acceptHeaderLocaleResolver.setDefaultLocale(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Locale resolveLocale(@NotNull HttpServletRequest request) {
|
||||
String lang = request.getParameter(PARAM);
|
||||
if (null == lang) {
|
||||
return acceptHeaderLocaleResolver.resolveLocale(request);
|
||||
} else {
|
||||
Locale loc = new Locale(lang);
|
||||
List<Locale.LanguageRange> priorityList = new ArrayList<>();
|
||||
priorityList.add(new Locale.LanguageRange(loc.toLanguageTag(), 1.0));
|
||||
priorityList.add(new Locale.LanguageRange(loc.getLanguage(), 0.9));
|
||||
priorityList.add(new Locale.LanguageRange(Locale.ENGLISH.getLanguage(), 0.3));
|
||||
|
||||
Locale pick = I18n.pickLocale(priorityList, supportedLocales, Locale.ENGLISH);
|
||||
log.debug("Picked locale: {} amongst {}", pick, priorityList);
|
||||
return pick;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setLocale(@NotNull HttpServletRequest request, HttpServletResponse response, Locale locale) {
|
||||
//this.locale = locale;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.view;
|
||||
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ViewModelInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
if (null != modelAndView) {
|
||||
modelAndView.addObject("title", "Title~!!!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.view;
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.elex_project.freesia;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
public final class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.elex_project.freesia;
|
||||
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.mustache.MustacheEnvironmentCollector;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public final class Config {
|
||||
@Value("elex.view.template.default")
|
||||
private String templateDefaultValue;
|
||||
|
||||
@Bean
|
||||
public Mustache.Compiler mustacheCompiler(
|
||||
Mustache.TemplateLoader templateLoader,
|
||||
Environment environment) {
|
||||
|
||||
MustacheEnvironmentCollector collector
|
||||
= new MustacheEnvironmentCollector();
|
||||
collector.setEnvironment(environment);
|
||||
|
||||
return Mustache.compiler()
|
||||
.defaultValue(templateDefaultValue)
|
||||
.withLoader(templateLoader)
|
||||
.withCollector(collector);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
/*@Bean
|
||||
public HttpTraceRepository httpTraceRepository() {
|
||||
return new InMemoryHttpTraceRepository();
|
||||
}*/
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.elex_project.freesia.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class Home {
|
||||
@GetMapping(value = "/")
|
||||
public ModelAndView home() {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
return new ModelAndView("home", map);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package com.elex_project.freesia.controller;
|
||||
@@ -1 +0,0 @@
|
||||
package com.elex_project.freesia.model;
|
||||
@@ -1 +0,0 @@
|
||||
package com.elex_project.freesia;
|
||||
@@ -1 +0,0 @@
|
||||
package com.elex_project.freesia.view;
|
||||
@@ -1,39 +1,82 @@
|
||||
elex:
|
||||
view:
|
||||
template:
|
||||
default: "[!UNDEFINED]"
|
||||
server:
|
||||
port: 8080
|
||||
asgard:
|
||||
locale:
|
||||
param: lang
|
||||
spring:
|
||||
application:
|
||||
name: Freesia
|
||||
name: Asgard
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd'T'HH:mm:ss
|
||||
datasource:
|
||||
url: jdbc:mariadb://localhost:3306/freesia
|
||||
driver-class-name: org.mariadb.jdbc.Driver
|
||||
url: jdbc:h2:~/asgard/test; #jdbc:mariadb://localhost:3306/asgard
|
||||
driver-class-name: org.h2.Driver #org.mariadb.jdbc.Driver
|
||||
username: elex
|
||||
password: test
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
path: /h2-console
|
||||
jpa:
|
||||
open-in-view: false
|
||||
generate-ddl: true
|
||||
show-sql: true
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
ddl-auto: update
|
||||
database-platform: org.hibernate.dialect.H2Dialect
|
||||
thymeleaf:
|
||||
suffix: .html
|
||||
messages:
|
||||
basename: i18n/messages
|
||||
fallback-to-system-locale: false
|
||||
security:
|
||||
user:
|
||||
name: elex
|
||||
password: test
|
||||
logging:
|
||||
path: ${user.home}/logs/freesia
|
||||
path: ${user.home}/asgard/logs
|
||||
level:
|
||||
root: debug
|
||||
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
max-file-size: 1MB
|
||||
max-request-size: 10MB
|
||||
server:
|
||||
port: 8080
|
||||
server-header: Elex Project
|
||||
error:
|
||||
path: /error
|
||||
whitelabel:
|
||||
enabled: true
|
||||
tomcat:
|
||||
accept-count: 100
|
||||
accesslog:
|
||||
enabled: true
|
||||
pattern: "%{yyyy-MM-dd HH:mm:ss}t\t%s\t%r\t%{User-Agent}i\t%{Referer}i\t%a\t%b\t%D"
|
||||
directory: ${user.home}/asgard/accesslog
|
||||
max-days: 90
|
||||
rotate: true
|
||||
suffix: .log
|
||||
max-connections: 8192
|
||||
remote-ip:
|
||||
host-header: X-Forwarded-Host
|
||||
port-header: X-Forwarded-Port
|
||||
protocol-header: X-Forwarded-Proto
|
||||
remote-ip-header: X-Forwarded-For
|
||||
servlet:
|
||||
encoding:
|
||||
charset: utf-8
|
||||
force-response: true
|
||||
---
|
||||
|
||||
spring:
|
||||
config:
|
||||
active:
|
||||
on-profile: production
|
||||
server:
|
||||
tomcat:
|
||||
accesslog:
|
||||
directory: /var/log/asgard/accesslog
|
||||
logging:
|
||||
path: /var/log/freesia
|
||||
path: /var/log/asgard
|
||||
level:
|
||||
root: info
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
ELEX's _ .-') .-') _ ('-.
|
||||
( \( -O ) ( OO ) ) ( OO ).-.
|
||||
,--. .-'),-----. ,--. ,--. ,------. ,--./ ,--,' / . --. / ,--.
|
||||
.-')| ,|( OO' .-. ' | | | | | /`. '| \ | |\ | \-. \ | |.-')
|
||||
( OO |(_|/ | | | | | | | .-') | / | || \| | ).-'-' | | | | OO )
|
||||
| `-'| |\_) | |\| | | |_|( OO )| |_.' || . |/ \| |_.' | | |`-' |
|
||||
,--. | | \ | | | | | | | `-' /| . '.'| |\ | | .-. |(| '---.'
|
||||
| '-' / `' '-' '(' '-'(_.-' | |\ \ | | \ | | | | | | |
|
||||
`-----' `-----' `-----' `--' '--'`--' `--' `--' `--' `------'
|
||||
|
||||
8
app/src/main/resources/i18n/messages.properties
Normal file
8
app/src/main/resources/i18n/messages.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# Project Asgard
|
||||
#
|
||||
# Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
# https://www.elex-project.com/
|
||||
#
|
||||
|
||||
hello.text = Hello
|
||||
8
app/src/main/resources/i18n/messages_ko.properties
Normal file
8
app/src/main/resources/i18n/messages_ko.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# Project Asgard
|
||||
#
|
||||
# Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
# https://www.elex-project.com/
|
||||
#
|
||||
|
||||
hello.text = 안녕
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2021. Elex co.,ltd. All rights reserved.
|
||||
~ developed by <developer@elex-project.com>
|
||||
~
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="com.elex_project.freesia" level="debug" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
<root level="info">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
1
app/src/main/resources/static/bundle.css
Normal file
1
app/src/main/resources/static/bundle.css
Normal file
File diff suppressed because one or more lines are too long
2
app/src/main/resources/static/bundle.js
Normal file
2
app/src/main/resources/static/bundle.js
Normal file
File diff suppressed because one or more lines are too long
12
app/src/main/resources/static/humans.txt
Normal file
12
app/src/main/resources/static/humans.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
/* TEAM */
|
||||
Boss: Elex
|
||||
Site: https://www.elex.pe.kr/
|
||||
Facebook:
|
||||
|
||||
/* THANKS */
|
||||
Name:
|
||||
|
||||
/* SITE */
|
||||
Front-end: HTML5, CSS3, Javascript, Material Design Components, Node-js(yarn, webpack, babel), Scss
|
||||
Back-end: Spring-boot, Mustache, Hibernate
|
||||
Server: Docker, MariaDB, Tomcat, Nginx, Linux
|
||||
3
app/src/main/resources/static/robots.txt
Normal file
3
app/src/main/resources/static/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
User-agent: *
|
||||
Disallow: /cgi-bin/
|
||||
Sitemap: https://www.elex-project.com/sitemap.xml
|
||||
167
app/src/main/resources/templates/document.html
Normal file
167
app/src/main/resources/templates/document.html
Normal file
@@ -0,0 +1,167 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{html_lang}}">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
{{> fragments/meta}}
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||
<link rel="author" href="/humans.txt" />
|
||||
<link rel="stylesheet" href="/bundle.css" />
|
||||
<title>{{title}}</title>
|
||||
<script src="/bundle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<aside id="layout-drawer" class="mdc-drawer mdc-drawer--dismissible">
|
||||
<div class="mdc-drawer__header">
|
||||
<p>Hello</p>
|
||||
</div>
|
||||
<div class="mdc-drawer__content">
|
||||
<nav class="mdc-list mdc-list--dense">
|
||||
<a class="mdc-list-item mdc-list-item--activated" href="#" aria-current="page">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Inbox</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Outgoing</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts Drafts Drafts Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item mdc-list-item--depth-1" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item mdc-list-item--depth-1" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts Drafts Drafts Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item " href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item mdc-list-item--depth-2" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts Drafts Drafts Drafts Drafts Drafts Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Drafts</span>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
<div id="layout-content" class="mdc-drawer-app-content">
|
||||
<header class="mdc-top-app-bar mdc-top-app-bar--fixed">
|
||||
<div class="mdc-elevation-overlay"></div>
|
||||
<div class="mdc-top-app-bar__row">
|
||||
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
|
||||
<button class="material-icons mdc-top-app-bar__navigation-icon mdc-icon-button"
|
||||
aria-label="Open navigation menu">menu</button>
|
||||
<span class="mdc-top-app-bar__title">{{title}}</span>
|
||||
</section>
|
||||
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-end" role="toolbar">
|
||||
<button class="material-icons mdc-top-app-bar__action-item mdc-icon-button"
|
||||
aria-label="Favorite">favorite</button>
|
||||
<button class="material-icons mdc-top-app-bar__action-item mdc-icon-button"
|
||||
aria-label="Search">search</button>
|
||||
<div class="mdc-menu-surface--anchor">
|
||||
<button id="btn-overflow" class="material-icons mdc-top-app-bar__action-item mdc-icon-button"
|
||||
aria-label="Options">more_vert</button>
|
||||
<div class="mdc-menu mdc-menu-surface">
|
||||
<ul class="mdc-list" role="menu" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
||||
<li class="mdc-list-item" role="menuitem">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">A Menu Item</span>
|
||||
</li>
|
||||
<li class="mdc-list-item" role="menuitem">
|
||||
<span class="mdc-list-item__ripple"></span>
|
||||
<span class="mdc-list-item__text">Another Menu Item</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</header>
|
||||
<div id="layout-main" class="mdc-top-app-bar--fixed-adjust">
|
||||
<main class="mdc-layout-grid">
|
||||
<article>
|
||||
<h1>Heading 1</h1>
|
||||
<p>Ha<em>Hehe</em>hoho.</p>
|
||||
<button class="mdc-button mdc-button--raised">
|
||||
<div class="mdc-button__ripple"></div>
|
||||
<span class="mdc-button__label">Button</span>
|
||||
</button>
|
||||
<div>
|
||||
<label class="mdc-text-field mdc-text-field--filled username">
|
||||
<span class="mdc-text-field__ripple"></span>
|
||||
<input type="text" class="mdc-text-field__input" aria-labelledby="username-label" name="username">
|
||||
<span class="mdc-floating-label" id="username-label">Username</span>
|
||||
<span class="mdc-line-ripple"></span>
|
||||
</label>
|
||||
<label class="mdc-text-field mdc-text-field--filled password">
|
||||
<span class="mdc-text-field__ripple"></span>
|
||||
<input type="password" class="mdc-text-field__input" aria-labelledby="password-label" name="password">
|
||||
<span class="mdc-floating-label" id="password-label">Password</span>
|
||||
<span class="mdc-line-ripple"></span>
|
||||
</label>
|
||||
</div>
|
||||
<blockquote>
|
||||
Hahaha
|
||||
</blockquote>
|
||||
<p>
|
||||
동해물과 백두산이 마르고 닳도록
|
||||
</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
|
||||
dolore magna
|
||||
aliqua. <strong>Ut enim ad minim</strong> veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
Duis
|
||||
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
|
||||
sint
|
||||
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
|
||||
dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
Duis
|
||||
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
|
||||
sint
|
||||
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
</article>
|
||||
</main>
|
||||
<footer class="mdc-layout-grid">
|
||||
<p>Copyright © 2021</p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
28
app/src/main/resources/templates/error.html
Normal file
28
app/src/main/resources/templates/error.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{status}} - {{message}}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&family=Ubuntu+Mono&display=swap" rel="stylesheet"> <style>
|
||||
html {font-family: 'Ubuntu Mono', monospace; font-size: 17px; line-height: 1.3;}
|
||||
body{background-color: #404552; color: #c8c8c8;}
|
||||
input {background: none; color: inherit; outline: none; border: 0; appearance: none;}
|
||||
.green {color: #adff2f;} .blue {color: #5294e2;}
|
||||
.inline {display:flex;} .inline > *:last-child {flex-grow: 1;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p class="inline">
|
||||
<span class="green">www-user@elex-project.com</span><span>:</span>
|
||||
<span class="blue">{{path}}</span><span>$ </span><span>http get {{path}}</span>
|
||||
</p>
|
||||
<p>{{status}} - {{message}}</p>
|
||||
<p>Trace:<br /> {{trace}}</p>
|
||||
<p class="inline">
|
||||
<span class="green">www-user@elex-project.com</span><span>:</span>
|
||||
<span class="blue">{{path}}</span><span>$ </span><input type="text"/>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
13
app/src/main/resources/templates/error/404.html
Normal file
13
app/src/main/resources/templates/error/404.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{status}} - {{message}}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<p>Oops-404!</p>
|
||||
<h1>{{status}}</h1>
|
||||
<p>{{message}}</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
<p>Haha</p>
|
||||
3
app/src/main/resources/templates/fragments/footer.html
Normal file
3
app/src/main/resources/templates/fragments/footer.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<footer th:fragment="footer">
|
||||
Copyright ©
|
||||
</footer>
|
||||
14
app/src/main/resources/templates/fragments/meta.html
Normal file
14
app/src/main/resources/templates/fragments/meta.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<head th:fragment="meta">
|
||||
<meta property="og:title" content="{{title}}" />
|
||||
<meta property="og:url" content="{{url}}" />
|
||||
<meta name="description" property="og:description" content="{{description}}" />
|
||||
<meta property="og:locale" content="{{html_lang}}" />
|
||||
<meta property="og:site_name" content="Elex Project" />
|
||||
<meta property="og:image" content="{{image}}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:article:section" content="{{section}}" />
|
||||
<meta name="keyword" property="og:article:tag" content="{{tag}}" />
|
||||
<meta property="og:article:published_time" content="{{published_time}}" />
|
||||
<meta property="og:article:modified_time" content="{{modified_time}}" />
|
||||
<meta name="author" property="og:article:author" content="{{author}}"/>
|
||||
</head>
|
||||
40
app/src/main/resources/templates/home.html
Normal file
40
app/src/main/resources/templates/home.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title th:text="${title}">{{title}}</title>
|
||||
<th:block th:include="~{fragments/meta :: meta}"></th:block>
|
||||
<link rel="stylesheet" href="/persona.min.css" />
|
||||
<script>
|
||||
let toggle = function () {
|
||||
const elem = document.querySelector(".layout");
|
||||
elem.classList.toggle("closed");
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<div class="sidebar">
|
||||
<nav class="nav">
|
||||
<ul>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<header class="header">
|
||||
<span class="icon-button material-icons" onclick="toggle();">menu</span>
|
||||
<h1 class="grow" th:text="${title}">{{title}}</h1>
|
||||
</header>
|
||||
<div class="main">
|
||||
<main>
|
||||
<p th:text="#{hello.text}">{{#i18n}}hello.text{{/i18n}}</p>
|
||||
|
||||
<p>...</p>
|
||||
</main>
|
||||
<footer th:replace="~{fragments/footer :: footer}">
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello</p>
|
||||
{{>fragments/a}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,11 @@
|
||||
package com.elex_project.freesia;
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Project Asgard
|
||||
*
|
||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||
* https://www.elex-project.com/
|
||||
*/
|
||||
|
||||
package com.elex_project.asgard.supplements;
|
||||
|
||||
import com.elex_project.abraxas.Console;
|
||||
import com.elex_project.abraxas.IOz;
|
||||
import com.vladsch.flexmark.util.ast.Node;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class MarkdownTest {
|
||||
@Test
|
||||
void render() throws IOException {
|
||||
String s = IOz.readStringFrom(getClass().getResourceAsStream("/sample.md"));
|
||||
Markdown markdown = new Markdown();
|
||||
Node doc = markdown.parse(s);
|
||||
String html = markdown.render(doc);
|
||||
Console.writeLine(html);
|
||||
Map<String, List<String>> frontMatter = markdown.frontMatter(doc);
|
||||
for (String key : frontMatter.keySet()) {
|
||||
Console.write(key);
|
||||
for (String v : frontMatter.get(key)) {
|
||||
Console.write(v);
|
||||
Console.write(" ");
|
||||
}
|
||||
Console.writeLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user