MD编辑器更新

UI更新
This commit is contained in:
2026-09-23 14:07:19 +08:00
parent 429e8a7bb7
commit ec21ba0876
379 changed files with 15504 additions and 606 deletions
@@ -1,6 +1,7 @@
package com.accounting.controller; package com.accounting.controller;
import com.accounting.dto.NoteAttachmentResponse; import com.accounting.dto.NoteAttachmentResponse;
import com.accounting.dto.NoteFolderAssignRequest;
import com.accounting.dto.NoteImportRequest; import com.accounting.dto.NoteImportRequest;
import com.accounting.dto.NotePageResponse; import com.accounting.dto.NotePageResponse;
import com.accounting.dto.NoteRequest; import com.accounting.dto.NoteRequest;
@@ -45,10 +46,14 @@ public class NoteController {
@RequestParam(defaultValue = "20") int size, @RequestParam(defaultValue = "20") int size,
@RequestParam(required = false) String keyword, @RequestParam(required = false) String keyword,
@RequestParam(required = false) String tag, @RequestParam(required = false) String tag,
@RequestParam(defaultValue = "all") String scope,
@RequestParam(required = false) Long folderId,
@RequestParam(defaultValue = "updated") String sort,
Authentication authentication) { Authentication authentication) {
Long userId = getUserId(authentication); Long userId = getUserId(authentication);
return ResponseEntity.ok(noteService.list(userId, keyword, tag, page, size)); return ResponseEntity.ok(
noteService.list(userId, scope, folderId, keyword, tag, sort, page, size));
} }
@Operation(summary = "查询笔记详情(含正文)") @Operation(summary = "查询笔记详情(含正文)")
@@ -94,7 +99,7 @@ public class NoteController {
Authentication authentication) { Authentication authentication) {
Long userId = getUserId(authentication); Long userId = getUserId(authentication);
int imported = noteService.importBatch(userId, request.getNotes()); int imported = noteService.importBatch(userId, request.getNotes(), request.getFolderId());
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
result.put("success", true); result.put("success", true);
@@ -102,6 +107,21 @@ public class NoteController {
return ResponseEntity.ok(result); return ResponseEntity.ok(result);
} }
@Operation(summary = "把笔记移动到某个目录(folderId 为 null 表示移到未分类)")
@PutMapping("/{id}/folder")
public ResponseEntity<Map<String, Object>> assignFolder(
@PathVariable Long id,
@RequestBody NoteFolderAssignRequest request,
Authentication authentication) {
Long userId = getUserId(authentication);
noteService.assignFolder(userId, id, request.getFolderId());
Map<String, Object> result = new HashMap<>();
result.put("success", true);
return ResponseEntity.ok(result);
}
@Operation(summary = "上传图片附件,返回可直接在 Markdown 中引用的地址") @Operation(summary = "上传图片附件,返回可直接在 Markdown 中引用的地址")
@PostMapping("/attachments") @PostMapping("/attachments")
public ResponseEntity<NoteAttachmentResponse> uploadAttachment( public ResponseEntity<NoteAttachmentResponse> uploadAttachment(
@@ -0,0 +1,106 @@
package com.accounting.controller;
import com.accounting.dto.FolderMoveRequest;
import com.accounting.dto.FolderNode;
import com.accounting.dto.FolderRequest;
import com.accounting.dto.FolderTreeResponse;
import com.accounting.entity.User;
import com.accounting.mapper.UserMapper;
import com.accounting.service.NoteFolderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* 笔记目录
*
* <p>路径挂在 {@code /api/notes/folders} 下,和 {@code /api/notes/{id}} 并存 ——
* Spring 的路径匹配对字面量段的优先级高于变量段,所以 {@code folders} 不会被
* 当成笔记 id,这一点和已有的 {@code /api/notes/tags} 是同一个机制。</p>
*/
@Tag(name = "笔记目录", description = "笔记文件夹的增删改查与移动")
@RestController
@RequestMapping("/api/notes/folders")
public class NoteFolderController {
@Autowired
private NoteFolderService folderService;
@Autowired
private UserMapper userMapper;
@Operation(summary = "获取目录树(含各目录的笔记数,数量包含子目录)")
@GetMapping
public ResponseEntity<FolderTreeResponse> tree(Authentication authentication) {
return ResponseEntity.ok(folderService.tree(getUserId(authentication)));
}
@Operation(summary = "新建目录")
@PostMapping
public ResponseEntity<FolderNode> create(
@RequestBody FolderRequest request,
Authentication authentication) {
Long userId = getUserId(authentication);
return ResponseEntity.ok(
folderService.create(userId, request.getName(), request.getParentId()));
}
@Operation(summary = "重命名目录")
@PutMapping("/{id}")
public ResponseEntity<Map<String, Object>> rename(
@PathVariable Long id,
@RequestBody FolderRequest request,
Authentication authentication) {
folderService.rename(getUserId(authentication), id, request.getName());
return ResponseEntity.ok(ok());
}
@Operation(summary = "移动目录到新的父目录(parentId 为 null 表示移到根目录)")
@PutMapping("/{id}/move")
public ResponseEntity<Map<String, Object>> move(
@PathVariable Long id,
@RequestBody FolderMoveRequest request,
Authentication authentication) {
folderService.move(getUserId(authentication), id, request.getParentId());
return ResponseEntity.ok(ok());
}
@Operation(summary = "删除目录(子目录与笔记上移到父目录,不删除笔记)")
@DeleteMapping("/{id}")
public ResponseEntity<Map<String, Object>> delete(
@PathVariable Long id,
Authentication authentication) {
folderService.delete(getUserId(authentication), id);
return ResponseEntity.ok(ok());
}
private Map<String, Object> ok() {
Map<String, Object> result = new HashMap<>();
result.put("success", true);
return result;
}
private Long getUserId(Authentication authentication) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String username = userDetails.getUsername();
User user = userMapper.selectOne(
new LambdaQueryWrapper<User>().eq(User::getUsername, username)
);
if (user == null) {
throw new IllegalArgumentException("用户不存在");
}
return user.getId();
}
}
@@ -0,0 +1,14 @@
package com.accounting.dto;
import lombok.Data;
/**
* 移动目录(改变它的父目录)
*
* <p>{@code parentId} 为 null 表示移动到根目录下。</p>
*/
@Data
public class FolderMoveRequest {
private Long parentId;
}
@@ -0,0 +1,30 @@
package com.accounting.dto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 目录树节点
*/
@Data
public class FolderNode {
private Long id;
private String name;
/** 父目录 ID,null = 根目录下的一级目录 */
private Long parentId;
/**
* 该目录下的笔记数(**含所有子目录**)
*
* <p>这样父目录的数量不会和"点进去看到的条数"对不上:
* 列表默认就是按"当前目录含子目录"来查的,两边口径一致。</p>
*/
private int noteCount;
private List<FolderNode> children = new ArrayList<>();
}
@@ -0,0 +1,15 @@
package com.accounting.dto;
import lombok.Data;
/**
* 新建 / 重命名目录
*/
@Data
public class FolderRequest {
private String name;
/** 新建时指定父目录;null = 建在根目录下 */
private Long parentId;
}
@@ -0,0 +1,22 @@
package com.accounting.dto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 目录树接口的返回体
*/
@Data
public class FolderTreeResponse {
/** 目录树(只含真实目录,根层级) */
private List<FolderNode> folders = new ArrayList<>();
/** 未分类的笔记数 */
private int uncategorizedCount;
/** 全部笔记数,含未分类 */
private int totalCount;
}
@@ -0,0 +1,17 @@
package com.accounting.dto;
import lombok.Data;
/**
* 把笔记移动到某个目录
*
* <p>单独开一个接口而不是复用 {@code PUT /api/notes/{id}},是因为后者是
* 部分更新语义(字段为 null 表示"不改动"),没法表达"把笔记移回未分类"。
* 这里 folderId 为 null 是明确的"未分类"。</p>
*/
@Data
public class NoteFolderAssignRequest {
/** 目标目录 ID,null = 移到未分类 */
private Long folderId;
}
@@ -20,6 +20,9 @@ public class NoteImportRequest {
@Valid @Valid
private List<Item> notes; private List<Item> notes;
/** 导入到哪个目录;null = 未分类。由前端按当前所在目录传入 */
private Long folderId;
@Data @Data
public static class Item { public static class Item {
@@ -16,6 +16,9 @@ public class NoteListItem {
private Long id; private Long id;
/** 所属目录 ID,null = 未分类 */
private Long folderId;
private String title; private String title;
/** 摘要,由正文自动提取 */ /** 摘要,由正文自动提取 */
@@ -13,6 +13,9 @@ public class NoteResponse {
private Long id; private Long id;
/** 所属目录 ID,null = 未分类 */
private Long folderId;
private String title; private String title;
private String content; private String content;
@@ -24,6 +24,9 @@ public class Note {
private Long userId; private Long userId;
/** 所属目录 ID,null = 未分类 */
private Long folderId;
private String title; private String title;
/** Markdown 正文 */ /** Markdown 正文 */
@@ -0,0 +1,38 @@
package com.accounting.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 笔记目录(文件夹)
*
* <p>树形结构,parentId 为 null 表示根目录下的目录。</p>
*/
@Data
@TableName("note_folder")
public class NoteFolder {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
/** 父目录 ID,null = 位于根目录 */
private Long parentId;
private String name;
private Integer sortOrder;
@TableLogic
private Integer deleted;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
@@ -0,0 +1,9 @@
package com.accounting.mapper;
import com.accounting.entity.NoteFolder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface NoteFolderMapper extends BaseMapper<NoteFolder> {
}
@@ -3,7 +3,26 @@ package com.accounting.mapper;
import com.accounting.entity.Note; import com.accounting.entity.Note;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
@Mapper @Mapper
public interface NoteMapper extends BaseMapper<Note> { public interface NoteMapper extends BaseMapper<Note> {
/**
* 按目录统计笔记数(只统计当前目录直接挂的,不含子目录)
*
* <p>用注解写原生 SQL 是为了能 group by 聚合 —— BaseMapper 不带这个能力。
* 这里显式带上 {@code deleted = 0},因为自定义 SQL 不会走 MyBatis-Plus
* 的逻辑删除自动拼接。</p>
*
* <p>folder_id 为 NULL 的那一行表示未分类笔记。</p>
*/
@Select("SELECT folder_id, COUNT(*) AS cnt FROM note "
+ "WHERE user_id = #{userId} AND deleted = 0 "
+ "GROUP BY folder_id")
List<Map<String, Object>> countGroupByFolder(@Param("userId") Long userId);
} }
@@ -0,0 +1,295 @@
package com.accounting.service;
import com.accounting.dto.FolderNode;
import com.accounting.dto.FolderTreeResponse;
import com.accounting.entity.Note;
import com.accounting.entity.NoteFolder;
import com.accounting.mapper.NoteFolderMapper;
import com.accounting.mapper.NoteMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 笔记目录(文件夹)
*
* <p>树的深度和节点数在个人使用场景下都很小(几百个顶天),
* 所以不做递归 SQL,一次性把该用户的目录全查出来在内存里组树。</p>
*/
@Service
public class NoteFolderService {
@Autowired
private NoteFolderMapper folderMapper;
@Autowired
private NoteMapper noteMapper;
private static final int NAME_MAX_LENGTH = 100;
// ==================================================================
// 查询
// ==================================================================
/**
* 目录树 + 各目录的笔记数
*
* <p>目录上的笔记数是**含子目录**的累计值,和列表接口
* 「按当前目录含子目录查询」的口径保持一致,
* 不会出现"父目录显示 5、点进去只有 2"的困惑。</p>
*/
public FolderTreeResponse tree(Long userId) {
List<NoteFolder> folders = folderMapper.selectList(
new LambdaQueryWrapper<NoteFolder>()
.eq(NoteFolder::getUserId, userId)
.orderByAsc(NoteFolder::getSortOrder)
.orderByAsc(NoteFolder::getId));
Map<Long, Integer> directCounts = new HashMap<>();
int uncategorized = 0;
int total = 0;
for (Map<String, Object> row : noteMapper.countGroupByFolder(userId)) {
int count = toInt(row.get("cnt"));
total += count;
Object folderId = row.get("folder_id");
if (folderId == null) {
uncategorized = count;
} else {
directCounts.put(((Number) folderId).longValue(), count);
}
}
Map<Long, FolderNode> nodeById = new LinkedHashMap<>();
for (NoteFolder folder : folders) {
FolderNode node = new FolderNode();
node.setId(folder.getId());
node.setName(folder.getName());
node.setParentId(folder.getParentId());
node.setNoteCount(directCounts.getOrDefault(folder.getId(), 0));
nodeById.put(folder.getId(), node);
}
List<FolderNode> roots = new ArrayList<>();
for (FolderNode node : nodeById.values()) {
FolderNode parent = node.getParentId() == null ? null : nodeById.get(node.getParentId());
// 父目录查不到(数据异常)时当根节点处理,避免整棵子树丢失
if (parent == null) {
roots.add(node);
} else {
parent.getChildren().add(node);
}
}
// 自底向上把子目录的数量累加到父目录
for (FolderNode root : roots) {
accumulateCount(root);
}
FolderTreeResponse response = new FolderTreeResponse();
response.setFolders(roots);
response.setUncategorizedCount(uncategorized);
response.setTotalCount(total);
return response;
}
private int accumulateCount(FolderNode node) {
int sum = node.getNoteCount();
for (FolderNode child : node.getChildren()) {
sum += accumulateCount(child);
}
node.setNoteCount(sum);
return sum;
}
/**
* 某个目录及其所有子孙目录的 id 集合(含自身)。
* NoteService 按目录查询笔记时用它拼 IN 条件。
*/
public Set<Long> subtreeIds(Long userId, Long rootId) {
if (rootId == null) {
return new LinkedHashSet<>();
}
List<NoteFolder> folders = folderMapper.selectList(
new LambdaQueryWrapper<NoteFolder>()
.select(NoteFolder::getId, NoteFolder::getParentId)
.eq(NoteFolder::getUserId, userId));
Map<Long, List<Long>> childrenOf = new HashMap<>();
for (NoteFolder folder : folders) {
childrenOf.computeIfAbsent(folder.getParentId(), k -> new ArrayList<>()).add(folder.getId());
}
Set<Long> result = new LinkedHashSet<>();
collect(rootId, childrenOf, result);
return result;
}
private void collect(Long id, Map<Long, List<Long>> childrenOf, Set<Long> result) {
// 正常情况下不会有环(move 里做了校验),这里再兜一层防止脏数据把请求拖死
if (!result.add(id)) {
return;
}
for (Long child : childrenOf.getOrDefault(id, List.of())) {
collect(child, childrenOf, result);
}
}
// ==================================================================
// 写入
// ==================================================================
@Transactional
public FolderNode create(Long userId, String name, Long parentId) {
String cleanName = requireName(name);
if (parentId != null) {
requireOwned(userId, parentId);
}
ensureNameNotTaken(userId, parentId, cleanName, null);
NoteFolder folder = new NoteFolder();
folder.setUserId(userId);
folder.setName(cleanName);
folder.setParentId(parentId);
folder.setSortOrder(0);
folderMapper.insert(folder);
FolderNode node = new FolderNode();
node.setId(folder.getId());
node.setName(folder.getName());
node.setParentId(folder.getParentId());
node.setNoteCount(0);
return node;
}
@Transactional
public void rename(Long userId, Long id, String name) {
NoteFolder folder = requireOwned(userId, id);
String cleanName = requireName(name);
ensureNameNotTaken(userId, folder.getParentId(), cleanName, id);
folder.setName(cleanName);
folderMapper.updateById(folder);
}
/**
* 移动目录到新的父目录
*/
@Transactional
public void move(Long userId, Long id, Long newParentId) {
NoteFolder folder = requireOwned(userId, id);
if (newParentId != null) {
requireOwned(userId, newParentId);
// 不能把目录挂到自己的子目录下,否则会形成一个断开的环
if (subtreeIds(userId, id).contains(newParentId)) {
throw new IllegalArgumentException("不能把目录移动到它自己的子目录里");
}
}
// 用 UpdateWrapper 而不是 updateById:后者会忽略 null 字段,
// 导致"移动到根目录"(parentId = null)静默失败
folderMapper.update(null, new LambdaUpdateWrapper<NoteFolder>()
.eq(NoteFolder::getId, id)
.eq(NoteFolder::getUserId, userId)
.set(NoteFolder::getParentId, newParentId));
}
/**
* 删除目录
*
* <p>子目录和笔记**上移到被删目录的父级**,不跟着删除 —— 先保数据,
* 用户真要把笔记一起清了应该去删笔记。</p>
*/
@Transactional
public void delete(Long userId, Long id) {
NoteFolder folder = requireOwned(userId, id);
Long newParentId = folder.getParentId();
// 1. 子目录上移
folderMapper.update(null, new LambdaUpdateWrapper<NoteFolder>()
.eq(NoteFolder::getUserId, userId)
.eq(NoteFolder::getParentId, id)
.set(NoteFolder::getParentId, newParentId));
// 2. 笔记上移(目录本身只是归类,笔记内容不受影响)
noteMapper.update(null, new LambdaUpdateWrapper<Note>()
.eq(Note::getUserId, userId)
.eq(Note::getFolderId, id)
.set(Note::getFolderId, newParentId));
// 3. 目录本身走逻辑删除
folderMapper.deleteById(id);
}
// ==================================================================
// 内部工具
// ==================================================================
public NoteFolder requireOwned(Long userId, Long id) {
NoteFolder folder = folderMapper.selectById(id);
if (folder == null || !folder.getUserId().equals(userId)) {
throw new IllegalArgumentException("目录不存在");
}
return folder;
}
/** 目标父目录在移动前也需要校验,供别的服务复用 */
public void requireOwnedIfPresent(Long userId, Long id) {
if (id != null) {
requireOwned(userId, id);
}
}
private String requireName(String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("目录名不能为空");
}
String clean = name.trim();
if (clean.length() > NAME_MAX_LENGTH) {
clean = clean.substring(0, NAME_MAX_LENGTH);
}
return clean;
}
/**
* 同一层级下不允许重名,否则用户分不清点哪个。
* [excludeId] 用于重命名时排除自己。
*/
private void ensureNameNotTaken(Long userId, Long parentId, String name, Long excludeId) {
LambdaQueryWrapper<NoteFolder> wrapper = new LambdaQueryWrapper<NoteFolder>()
.eq(NoteFolder::getUserId, userId)
.eq(NoteFolder::getName, name);
if (parentId == null) {
wrapper.isNull(NoteFolder::getParentId);
} else {
wrapper.eq(NoteFolder::getParentId, parentId);
}
if (excludeId != null) {
wrapper.ne(NoteFolder::getId, excludeId);
}
if (folderMapper.selectCount(wrapper) > 0) {
throw new IllegalArgumentException("同一层级下已经有叫「" + name + "」的目录了");
}
}
private static int toInt(Object value) {
return value instanceof Number ? ((Number) value).intValue() : 0;
}
}
@@ -8,6 +8,7 @@ import com.accounting.dto.NoteResponse;
import com.accounting.entity.Note; import com.accounting.entity.Note;
import com.accounting.mapper.NoteMapper; import com.accounting.mapper.NoteMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -19,6 +20,7 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -28,6 +30,16 @@ public class NoteService {
@Autowired @Autowired
private NoteMapper noteMapper; private NoteMapper noteMapper;
@Autowired
private NoteFolderService folderService;
/** 查询范围:全部笔记 */
private static final String SCOPE_ALL = "all";
/** 查询范围:未分类(folder_id 为空) */
private static final String SCOPE_UNCATEGORIZED = "uncategorized";
/** 查询范围:指定目录(含子目录) */
private static final String SCOPE_FOLDER = "folder";
/** 摘要最大长度 */ /** 摘要最大长度 */
private static final int SUMMARY_MAX_LENGTH = 150; private static final int SUMMARY_MAX_LENGTH = 150;
@@ -55,14 +67,18 @@ public class NoteService {
/** /**
* 分页查询笔记列表(不含正文) * 分页查询笔记列表(不含正文)
* *
* @param scope all(默认,全部笔记)/ uncategorized(未分类)/ folder(指定目录)
* @param folderId 仅 scope=folder 时有意义,查询含该目录及其所有子目录
* @param keyword 关键词,同时匹配标题和正文,可为空 * @param keyword 关键词,同时匹配标题和正文,可为空
* @param tag 标签精确匹配,可为空 * @param tag 标签精确匹配,可为空
* @param sort updated(默认)/ created / title
*/ */
public NotePageResponse list(Long userId, String keyword, String tag, int page, int size) { public NotePageResponse list(Long userId, String scope, Long folderId, String keyword,
String tag, String sort, int page, int size) {
int safePage = Math.max(page, 1); int safePage = Math.max(page, 1);
int safeSize = Math.min(Math.max(size, 1), MAX_PAGE_SIZE); int safeSize = Math.min(Math.max(size, 1), MAX_PAGE_SIZE);
long total = noteMapper.selectCount(buildListWrapper(userId, keyword, tag)); long total = noteMapper.selectCount(buildListWrapper(userId, scope, folderId, keyword, tag));
List<Note> rows; List<Note> rows;
if (total == 0) { if (total == 0) {
@@ -70,9 +86,7 @@ public class NoteService {
} else { } else {
int offset = (safePage - 1) * safeSize; int offset = (safePage - 1) * safeSize;
rows = noteMapper.selectList( rows = noteMapper.selectList(
buildListWrapper(userId, keyword, tag) applySort(buildListWrapper(userId, scope, folderId, keyword, tag), sort)
.orderByDesc(Note::getIsPinned)
.orderByDesc(Note::getUpdateTime)
// 项目里没有配置 MyBatis-Plus 的 PaginationInnerInterceptor, // 项目里没有配置 MyBatis-Plus 的 PaginationInnerInterceptor,
// selectPage 不会真正生成 LIMIT,所以这里直接拼。 // selectPage 不会真正生成 LIMIT,所以这里直接拼。
// offset/size 都是上面校验过的 int,不存在注入问题。 // offset/size 都是上面校验过的 int,不存在注入问题。
@@ -180,16 +194,39 @@ public class NoteService {
noteMapper.deleteById(note.getId()); noteMapper.deleteById(note.getId());
} }
/**
* 把笔记移动到某个目录
*
* <p>单独一个方法而不是走 {@link #update},是因为后者是部分更新语义
* (字段为 null 表示不改动),没法表达"移回未分类"。
* 这里的 folderId 为 null 是明确的「未分类」。</p>
*/
@Transactional
public void assignFolder(Long userId, Long noteId, Long folderId) {
requireOwnedNote(userId, noteId);
// 目标目录必须存在且属于当前用户;null 表示未分类,允许
folderService.requireOwnedIfPresent(userId, folderId);
// 用 UpdateWrapper:updateById 会忽略 null 字段,
// 导致"移回未分类"静默失败
noteMapper.update(null, new LambdaUpdateWrapper<Note>()
.eq(Note::getId, noteId)
.eq(Note::getUserId, userId)
.set(Note::getFolderId, folderId));
}
/** /**
* 批量导入 * 批量导入
* *
* @param folderId 导入到哪个目录,null = 未分类
* @return 实际写入的条数 * @return 实际写入的条数
*/ */
@Transactional @Transactional
public int importBatch(Long userId, List<NoteImportRequest.Item> items) { public int importBatch(Long userId, List<NoteImportRequest.Item> items, Long folderId) {
if (items == null || items.isEmpty()) { if (items == null || items.isEmpty()) {
return 0; return 0;
} }
folderService.requireOwnedIfPresent(userId, folderId);
int count = 0; int count = 0;
for (NoteImportRequest.Item item : items) { for (NoteImportRequest.Item item : items) {
@@ -197,6 +234,7 @@ public class NoteService {
Note note = new Note(); Note note = new Note();
note.setUserId(userId); note.setUserId(userId);
note.setFolderId(folderId);
note.setTitle(resolveTitle(item.getTitle(), content, item.getSourcePath())); note.setTitle(resolveTitle(item.getTitle(), content, item.getSourcePath()));
note.setContent(content); note.setContent(content);
note.setSummary(buildSummary(content)); note.setSummary(buildSummary(content));
@@ -213,10 +251,26 @@ public class NoteService {
// 内部工具 // 内部工具
// ================================================================== // ==================================================================
private LambdaQueryWrapper<Note> buildListWrapper(Long userId, String keyword, String tag) { private LambdaQueryWrapper<Note> buildListWrapper(Long userId, String scope, Long folderId,
String keyword, String tag) {
LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<Note>() LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<Note>()
.eq(Note::getUserId, userId); .eq(Note::getUserId, userId);
if (SCOPE_UNCATEGORIZED.equals(scope)) {
wrapper.isNull(Note::getFolderId);
} else if (SCOPE_FOLDER.equals(scope) && folderId != null) {
// 目录查询默认含子目录:点开「工作」应该看到「工作/服务器」里的东西,
// 而不是一片空白。目录上显示的笔记数也是这个口径。
Set<Long> ids = folderService.subtreeIds(userId, folderId);
if (ids.isEmpty()) {
// in() 传空集合会生成非法的 `IN ()`,这里直接让它查不到数据
wrapper.apply("1 = 0");
} else {
wrapper.in(Note::getFolderId, ids);
}
}
// scope=all(默认)或没传 folderId 时不做目录过滤
if (StringUtils.hasText(keyword)) { if (StringUtils.hasText(keyword)) {
String kw = keyword.trim(); String kw = keyword.trim();
wrapper.and(q -> q.like(Note::getTitle, kw).or().like(Note::getContent, kw)); wrapper.and(q -> q.like(Note::getTitle, kw).or().like(Note::getContent, kw));
@@ -230,6 +284,25 @@ public class NoteService {
return wrapper; return wrapper;
} }
/**
* 排序
*
* <p>置顶永远是第一排序键 —— 那是用户显式做的选择,
* 不该因为切了排序方式就被冲掉。</p>
*/
private LambdaQueryWrapper<Note> applySort(LambdaQueryWrapper<Note> wrapper, String sort) {
wrapper.orderByDesc(Note::getIsPinned);
if ("created".equals(sort)) {
wrapper.orderByDesc(Note::getCreateTime);
} else if ("title".equals(sort)) {
wrapper.orderByAsc(Note::getTitle);
} else {
wrapper.orderByDesc(Note::getUpdateTime);
}
return wrapper;
}
/** /**
* 取出属于该用户的笔记,找不到或不属于该用户都抛异常 * 取出属于该用户的笔记,找不到或不属于该用户都抛异常
*/ */
@@ -330,6 +403,7 @@ public class NoteService {
private NoteListItem toListItem(Note note) { private NoteListItem toListItem(Note note) {
NoteListItem item = new NoteListItem(); NoteListItem item = new NoteListItem();
item.setId(note.getId()); item.setId(note.getId());
item.setFolderId(note.getFolderId());
item.setTitle(note.getTitle()); item.setTitle(note.getTitle());
item.setSummary(note.getSummary()); item.setSummary(note.getSummary());
item.setTagList(parseTags(note.getTags())); item.setTagList(parseTags(note.getTags()));
@@ -341,6 +415,7 @@ public class NoteService {
private NoteResponse toResponse(Note note) { private NoteResponse toResponse(Note note) {
NoteResponse response = new NoteResponse(); NoteResponse response = new NoteResponse();
response.setId(note.getId()); response.setId(note.getId());
response.setFolderId(note.getFolderId());
response.setTitle(note.getTitle()); response.setTitle(note.getTitle());
response.setContent(note.getContent()); response.setContent(note.getContent());
response.setTagList(parseTags(note.getTags())); response.setTagList(parseTags(note.getTags()));
@@ -0,0 +1,31 @@
-- ===========================================================================
-- 笔记目录(文件夹)功能
--
-- 执行方式:
-- mysql -uroot -p accounting_db < migration_add_note_folder.sql
--
-- 目录是树形的:parent_id 为 NULL 表示根目录。
-- 笔记通过 note.folder_id 归属到某个目录,folder_id 为 NULL 表示未分类。
-- ===========================================================================
CREATE TABLE IF NOT EXISTS `note_folder` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '目录ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`parent_id` BIGINT DEFAULT NULL COMMENT '父目录ID,NULL 表示根目录',
`name` VARCHAR(100) NOT NULL COMMENT '目录名',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '同级排序,越小越靠前',
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除:0正常 1已删除',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
INDEX `idx_user_parent` (`user_id`, `deleted`, `parent_id`),
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='笔记目录表';
-- 笔记归属目录。OnDelete 用 SET NULL:目录被物理删除时笔记退回未分类,
-- 而不是跟着消失(业务上目录删除走的是"笔记上移到父目录",这里是兜底)
ALTER TABLE `note`
ADD COLUMN `folder_id` BIGINT DEFAULT NULL COMMENT '所属目录ID,NULL 表示未分类' AFTER `user_id`,
ADD INDEX `idx_user_folder` (`user_id`, `deleted`, `folder_id`),
ADD CONSTRAINT `fk_note_folder` FOREIGN KEY (`folder_id`)
REFERENCES `note_folder` (`id`) ON DELETE SET NULL;
+19 -1
View File
@@ -123,10 +123,26 @@ CREATE TABLE IF NOT EXISTS `gold_price` (
INDEX `idx_gold_date` (`gold_id`, `price_date`) COMMENT '索引:用于按日期查询' INDEX `idx_gold_date` (`gold_id`, `price_date`) COMMENT '索引:用于按日期查询'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='黄金价格记录表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='黄金价格记录表';
-- 笔记目录表
CREATE TABLE IF NOT EXISTS `note_folder` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '目录ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`parent_id` BIGINT DEFAULT NULL COMMENT '父目录ID,NULL 表示根目录',
`name` VARCHAR(100) NOT NULL COMMENT '目录名',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '同级排序',
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除:0正常 1已删除',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
INDEX `idx_user_parent` (`user_id`, `deleted`, `parent_id`),
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='笔记目录表';
-- 笔记表 -- 笔记表
CREATE TABLE IF NOT EXISTS `note` ( CREATE TABLE IF NOT EXISTS `note` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '笔记ID', `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '笔记ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID', `user_id` BIGINT NOT NULL COMMENT '用户ID',
`folder_id` BIGINT DEFAULT NULL COMMENT '所属目录ID,NULL 表示未分类',
`title` VARCHAR(200) NOT NULL COMMENT '标题', `title` VARCHAR(200) NOT NULL COMMENT '标题',
`content` LONGTEXT COMMENT 'Markdown正文', `content` LONGTEXT COMMENT 'Markdown正文',
`summary` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '摘要(列表页展示,避免查询正文)', `summary` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '摘要(列表页展示,避免查询正文)',
@@ -138,7 +154,9 @@ CREATE TABLE IF NOT EXISTS `note` (
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
INDEX `idx_user_updated` (`user_id`, `deleted`, `update_time`), INDEX `idx_user_updated` (`user_id`, `deleted`, `update_time`),
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE INDEX `idx_user_folder` (`user_id`, `deleted`, `folder_id`),
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE,
FOREIGN KEY (`folder_id`) REFERENCES `note_folder` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='笔记表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='笔记表';
-- 插入预设分类(支出) -- 插入预设分类(支出)
+288
View File
@@ -0,0 +1,288 @@
/* ===========================================================================
强宝小助手 —— 后台管理样式
布局约定:
#app-view 撑满视口高度,固定顶栏 + 左侧模块菜单,
右侧模块面板内部再分「工具栏 / 侧栏 / 内容」,
目录树和列表各自独立滚动 —— 这样长列表不会把整个页面顶下去。
=========================================================================== */
:root {
--brand: #C8956E;
--brand-light: #FFF6EC;
--text: #2B2B2B;
--text-dim: #8A8078;
--border: #EAE3DC;
--bg: #FAF8F5;
--danger: #D9534F;
}
* { box-sizing: border-box; }
body {
margin: 0; background: var(--bg); color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
font-size: 14px; line-height: 1.6;
}
button {
font-family: inherit; font-size: 14px; cursor: pointer;
border: 1px solid var(--border); background: #fff; color: var(--text);
padding: 7px 14px; border-radius: 8px; transition: .15s;
}
button:hover { border-color: var(--brand); color: var(--brand); }
button.primary { background: var(--brand); border-color: var(--brand); color: #fff; }
button.primary:hover { opacity: .88; color: #fff; }
button.danger:hover { border-color: var(--danger); color: var(--danger); }
input, textarea, select {
font-family: inherit; font-size: 14px; color: var(--text);
border: 1px solid var(--border); border-radius: 8px;
padding: 7px 12px; background: #fff; outline: none;
}
input, textarea { width: 100%; }
input:focus, textarea:focus, select:focus { border-color: var(--brand); }
select { cursor: pointer; padding: 7px 8px; }
/* ---------- 登录 ---------- */
#login-view {
min-height: 100vh; display: flex; align-items: center; justify-content: center;
}
.login-box {
width: 340px; background: #fff; padding: 36px 32px;
border-radius: 16px; border: 1px solid var(--border);
box-shadow: 0 8px 32px rgba(0,0,0,.05);
}
.login-box h1 { margin: 0 0 4px; font-size: 20px; }
.login-box p.sub { margin: 0 0 24px; color: var(--text-dim); font-size: 13px; }
.login-box .field { margin-bottom: 14px; }
.login-box .field label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--text-dim); }
.login-box button { width: 100%; margin-top: 8px; padding: 10px; }
/* ===========================================================================
主界面骨架
=========================================================================== */
#app-view {
height: 100vh; display: flex; flex-direction: column; overflow: hidden;
}
/* ---------- 顶栏:只放品牌 + 用户操作 ---------- */
.topbar {
flex-shrink: 0; z-index: 10;
height: 54px; display: flex; align-items: center; gap: 12px;
padding: 0 20px; background: #fff; border-bottom: 1px solid var(--border);
}
.topbar .spacer { flex: 1; }
.topbar .who { color: var(--text-dim); font-size: 13px; white-space: nowrap; }
.brand {
display: flex; align-items: center; gap: 8px;
font-size: 16px; font-weight: 600; color: #3E2723; white-space: nowrap;
}
.brand-icon { font-size: 19px; line-height: 1; }
.console { flex: 1; display: flex; min-height: 0; }
/* ---------- 左侧模块菜单 ---------- */
.module-nav {
width: 180px; flex-shrink: 0; overflow-y: auto;
background: #fff; border-right: 1px solid var(--border);
padding: 12px 10px;
}
.module-item {
display: flex; align-items: center; gap: 9px;
width: 100%; text-align: left; margin-bottom: 4px;
padding: 9px 12px; border: none; background: transparent;
border-radius: 8px; font-size: 14px; color: var(--text);
}
.module-item:hover { background: var(--brand-light); color: var(--brand); }
.module-item.active,
.module-item.active:hover { background: var(--brand); color: #fff; font-weight: 600; }
.mi-icon { font-size: 15px; line-height: 1; }
.mi-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ---------- 模块面板 ---------- */
.module-panel { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.toolbar {
flex-shrink: 0;
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
padding: 10px 16px; background: #fff; border-bottom: 1px solid var(--border);
}
.toolbar .spacer { flex: 1; }
.toolbar #search { flex: 0 1 320px; min-width: 150px; }
.module-body { flex: 1; display: flex; min-height: 0; }
/* ---------- 目录树 / 标签 侧栏 ---------- */
.sidebar {
width: 220px; flex-shrink: 0; overflow-y: auto;
background: #fff; border-right: 1px solid var(--border);
padding: 12px 10px;
}
/* ---------- 内容区 ---------- */
.content { flex: 1; min-width: 0; overflow-y: auto; padding: 16px 20px 48px; }
/* 窗口变窄时把模块菜单压成纯图标,给内容腾地方 */
@media (max-width: 1100px) {
.module-nav { width: 60px; padding: 12px 8px; }
.module-item { justify-content: center; padding: 10px 0; }
.mi-text { display: none; }
.sidebar { width: 190px; }
}
/* ===========================================================================
目录树
=========================================================================== */
.tree-row {
display: flex; align-items: center; gap: 4px;
padding: 5px 6px; border-radius: 6px; cursor: pointer;
user-select: none; position: relative;
}
.tree-row:hover { background: var(--brand-light); }
.tree-row.active { background: var(--brand); color: #fff; }
.tree-row.active .tree-count { color: rgba(255,255,255,.85); }
.tree-row.drop-target {
background: var(--brand-light);
outline: 2px dashed var(--brand); outline-offset: -2px;
}
.tree-toggle {
width: 16px; flex-shrink: 0; text-align: center;
font-size: 10px; color: var(--text-dim); transition: transform .15s;
}
.tree-toggle.open { transform: rotate(90deg); }
.tree-row.active .tree-toggle { color: rgba(255,255,255,.85); }
.tree-icon { flex-shrink: 0; font-size: 13px; }
.tree-name {
flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
font-size: 13.5px;
}
.tree-count { color: var(--text-dim); font-size: 12px; flex-shrink: 0; }
.tree-children { margin-left: 12px; }
.side-divider { height: 1px; background: var(--border); margin: 12px 4px; }
.side-title { font-size: 12px; color: var(--text-dim); padding: 0 6px 6px; }
/* ---------- 标签 ---------- */
.tag-chip {
display: block; width: 100%; text-align: left; border: none; background: transparent;
padding: 5px 8px; border-radius: 6px; margin-bottom: 2px; color: var(--text);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px;
}
.tag-chip:hover { background: var(--brand-light); color: var(--brand); }
.tag-chip.active { background: var(--brand); color: #fff; }
.tag-chip.active:hover { background: var(--brand); color: #fff; }
/* ===========================================================================
内容区内部
=========================================================================== */
.breadcrumb {
font-size: 13px; color: var(--text-dim); margin-bottom: 14px;
display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.breadcrumb .crumb { color: var(--brand); cursor: pointer; }
.breadcrumb .crumb:hover { text-decoration: underline; }
.breadcrumb .sep { color: #CCC; }
.breadcrumb .current { color: var(--text); font-weight: 600; }
#dropzone {
border: 2px dashed var(--border); border-radius: 12px; padding: 18px;
text-align: center; color: var(--text-dim); margin-bottom: 18px;
background: #fff; transition: .15s;
}
#dropzone.over { border-color: var(--brand); background: var(--brand-light); color: var(--brand); }
#dropzone-hint { color: var(--brand); font-weight: 600; }
.note-card {
background: #fff; border: 1px solid var(--border); border-radius: 12px;
padding: 14px 18px; margin-bottom: 10px; transition: .15s;
}
.note-card:hover { border-color: var(--brand); box-shadow: 0 4px 16px rgba(0,0,0,.04); }
.note-card.dragging { opacity: .45; }
.note-card .head { display: flex; align-items: baseline; gap: 8px; }
.note-card h3 {
margin: 0; font-size: 15px; font-weight: 600; flex: 1;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.note-card .pin { color: var(--brand); font-size: 13px; }
.note-card .summary {
color: var(--text-dim); font-size: 13px; margin: 6px 0 10px;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.note-card .meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.note-card .tag {
background: var(--brand-light); color: var(--brand);
padding: 2px 8px; border-radius: 4px; font-size: 12px;
}
.note-card .time { color: var(--text-dim); font-size: 12px; margin-left: auto; }
.note-card .actions { display: flex; gap: 6px; margin-left: 12px; }
.note-card .actions button { padding: 3px 10px; font-size: 12px; }
mark { background: #FFE9A8; color: inherit; padding: 0 1px; border-radius: 2px; }
.empty { text-align: center; color: var(--text-dim); padding: 60px 0; }
#loadmore { width: 100%; margin-top: 4px; padding: 10px; }
/* ===========================================================================
编辑器
=========================================================================== */
#editor {
position: fixed; inset: 0; background: rgba(0,0,0,.4);
display: none; align-items: center; justify-content: center; z-index: 100; padding: 24px;
}
#editor.open { display: flex; }
.editor-box {
background: #fff; border-radius: 16px; width: 100%; max-width: 1000px;
height: 100%; max-height: 760px; display: flex; flex-direction: column; overflow: hidden;
}
.editor-head {
padding: 14px 20px; border-bottom: 1px solid var(--border);
display: flex; gap: 12px; align-items: center;
}
.editor-head input.title { flex: 1; font-size: 15px; font-weight: 600; }
.editor-head input.tags { width: 220px; }
/* Vditor 需要父容器有确定高度才能撑满 */
.editor-body { flex: 1; min-height: 0; overflow: hidden; }
#vditor { height: 100%; }
.editor-foot {
padding: 12px 20px; border-top: 1px solid var(--border);
display: flex; gap: 10px; align-items: center;
}
.editor-foot .hint { color: var(--text-dim); font-size: 12px; margin-right: auto; }
/* Vditor 内部自带预览样式,这里只微调一下让它和页面配色一致 */
#vditor .vditor-reset { font-size: 14px; }
#vditor .vditor-toolbar { border-bottom: 1px solid var(--border); }
/* ===========================================================================
通用弹窗(重命名 / 新建目录 / 目录选择)
=========================================================================== */
#dialog {
position: fixed; inset: 0; background: rgba(0,0,0,.4);
display: none; align-items: center; justify-content: center; z-index: 200;
}
#dialog.open { display: flex; }
.dialog-box {
background: #fff; border-radius: 14px; padding: 24px;
width: 340px; box-shadow: 0 12px 40px rgba(0,0,0,.15);
}
.dialog-box h3 { margin: 0 0 14px; font-size: 16px; }
.dialog-box select { width: 100%; }
.dialog-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
/* ---------- 目录右键菜单 ---------- */
#ctx-menu {
position: absolute; z-index: 300; background: #fff;
border: 1px solid var(--border); border-radius: 8px; padding: 4px;
box-shadow: 0 8px 24px rgba(0,0,0,.12); min-width: 130px;
}
#ctx-menu div {
padding: 6px 12px; border-radius: 5px; cursor: pointer; font-size: 13.5px;
}
#ctx-menu div:hover { background: var(--brand-light); color: var(--brand); }
#ctx-menu div.danger { color: var(--danger); }
#ctx-menu div.danger:hover { background: #FDECEA; color: var(--danger); }
/* ---------- 提示 ---------- */
#toast {
position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%);
background: #2B2B2B; color: #fff; padding: 10px 20px; border-radius: 8px;
font-size: 13px; opacity: 0; pointer-events: none; transition: .25s; z-index: 999;
}
#toast.show { opacity: 1; }
#toast.err { background: var(--danger); }
File diff suppressed because it is too large Load Diff
+82 -596
View File
@@ -3,188 +3,17 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>笔记管理</title> <title>强宝小助手</title>
<style> <link rel="stylesheet" href="/admin/vendor/vditor/dist/index.css">
:root { <link rel="stylesheet" href="/admin/admin.css">
--brand: #C8956E;
--brand-light: #FFF6EC;
--text: #2B2B2B;
--text-dim: #8A8078;
--border: #EAE3DC;
--bg: #FAF8F5;
--danger: #D9534F;
}
* { box-sizing: border-box; }
body {
margin: 0; background: var(--bg); color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
font-size: 14px; line-height: 1.6;
}
button {
font-family: inherit; font-size: 14px; cursor: pointer;
border: 1px solid var(--border); background: #fff; color: var(--text);
padding: 7px 14px; border-radius: 8px; transition: .15s;
}
button:hover { border-color: var(--brand); color: var(--brand); }
button.primary { background: var(--brand); border-color: var(--brand); color: #fff; }
button.primary:hover { opacity: .88; color: #fff; }
button.danger:hover { border-color: var(--danger); color: var(--danger); }
input, textarea {
font-family: inherit; font-size: 14px; color: var(--text);
border: 1px solid var(--border); border-radius: 8px;
padding: 8px 12px; background: #fff; outline: none; width: 100%;
}
input:focus, textarea:focus { border-color: var(--brand); }
/* ---------- 登录 ---------- */
#login-view {
min-height: 100vh; display: flex; align-items: center; justify-content: center;
}
.login-box {
width: 340px; background: #fff; padding: 36px 32px;
border-radius: 16px; border: 1px solid var(--border);
box-shadow: 0 8px 32px rgba(0,0,0,.05);
}
.login-box h1 { margin: 0 0 4px; font-size: 20px; }
.login-box p.sub { margin: 0 0 24px; color: var(--text-dim); font-size: 13px; }
.login-box .field { margin-bottom: 14px; }
.login-box .field label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--text-dim); }
.login-box button { width: 100%; margin-top: 8px; padding: 10px; }
/* ---------- 主界面 ---------- */
header {
background: #fff; border-bottom: 1px solid var(--border);
padding: 14px 24px; display: flex; align-items: center; gap: 16px;
position: sticky; top: 0; z-index: 10;
}
header h1 { margin: 0; font-size: 17px; font-weight: 600; white-space: nowrap; }
header .search { flex: 1; max-width: 380px; }
header .spacer { flex: 1; }
header .who { color: var(--text-dim); font-size: 13px; white-space: nowrap; }
.layout { display: flex; gap: 24px; padding: 24px; align-items: flex-start; max-width: 1200px; margin: 0 auto; }
aside.tags {
width: 180px; flex-shrink: 0; background: #fff; border: 1px solid var(--border);
border-radius: 12px; padding: 16px; position: sticky; top: 84px;
}
aside.tags h3 { margin: 0 0 12px; font-size: 13px; color: var(--text-dim); font-weight: 500; }
.tag-chip {
display: block; width: 100%; text-align: left; border: none; background: transparent;
padding: 6px 10px; border-radius: 6px; margin-bottom: 2px; color: var(--text);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tag-chip:hover { background: var(--brand-light); color: var(--brand); }
.tag-chip.active { background: var(--brand); color: #fff; }
.tag-chip.active:hover { background: var(--brand); color: #fff; }
main { flex: 1; min-width: 0; }
#dropzone {
border: 2px dashed var(--border); border-radius: 12px; padding: 20px;
text-align: center; color: var(--text-dim); margin-bottom: 20px;
background: #fff; transition: .15s;
}
#dropzone.over { border-color: var(--brand); background: var(--brand-light); color: var(--brand); }
.note-card {
background: #fff; border: 1px solid var(--border); border-radius: 12px;
padding: 16px 18px; margin-bottom: 12px; transition: .15s;
}
.note-card:hover { border-color: var(--brand); box-shadow: 0 4px 16px rgba(0,0,0,.04); }
.note-card .head { display: flex; align-items: baseline; gap: 8px; }
.note-card h3 {
margin: 0; font-size: 15px; font-weight: 600; flex: 1;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.note-card .pin { color: var(--brand); font-size: 13px; }
.note-card .summary {
color: var(--text-dim); font-size: 13px; margin: 6px 0 10px;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.note-card .meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.note-card .tag {
background: var(--brand-light); color: var(--brand);
padding: 2px 8px; border-radius: 4px; font-size: 12px;
}
.note-card .time { color: var(--text-dim); font-size: 12px; margin-left: auto; }
.note-card .actions { display: flex; gap: 6px; margin-left: 12px; }
.note-card .actions button { padding: 3px 10px; font-size: 12px; }
.empty { text-align: center; color: var(--text-dim); padding: 60px 0; }
#loadmore { width: 100%; margin-top: 4px; padding: 10px; }
/* ---------- 编辑器 ---------- */
#editor {
position: fixed; inset: 0; background: rgba(0,0,0,.4);
display: none; align-items: center; justify-content: center; z-index: 100; padding: 24px;
}
#editor.open { display: flex; }
.editor-box {
background: #fff; border-radius: 16px; width: 100%; max-width: 1000px;
height: 100%; max-height: 760px; display: flex; flex-direction: column; overflow: hidden;
}
.editor-head {
padding: 14px 20px; border-bottom: 1px solid var(--border);
display: flex; gap: 12px; align-items: center;
}
.editor-head input.title { flex: 1; font-size: 15px; font-weight: 600; }
.editor-head input.tags { width: 220px; }
.editor-body { flex: 1; display: flex; min-height: 0; }
.editor-body textarea {
flex: 1; border: none; border-radius: 0; resize: none;
padding: 18px 20px; font-family: ui-monospace, Menlo, Consolas, monospace;
font-size: 13px; line-height: 1.7;
}
.editor-body textarea:focus { border: none; }
.editor-body .preview {
flex: 1; overflow-y: auto; padding: 18px 20px; border-left: 1px solid var(--border); background: #FCFBF9;
}
.editor-foot {
padding: 12px 20px; border-top: 1px solid var(--border);
display: flex; gap: 10px; align-items: center;
}
.editor-foot .hint { color: var(--text-dim); font-size: 12px; margin-right: auto; }
/* Markdown 预览样式 */
.preview h1, .preview h2, .preview h3 { margin: 18px 0 10px; line-height: 1.3; }
.preview h1 { font-size: 22px; border-bottom: 1px solid var(--border); padding-bottom: 6px; }
.preview h2 { font-size: 18px; }
.preview h3 { font-size: 15px; }
.preview p { margin: 10px 0; }
.preview code {
background: #F2EEE9; padding: 2px 5px; border-radius: 4px;
font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px;
}
.preview pre {
background: #2B2B2B; color: #F0EDEA; padding: 14px; border-radius: 8px; overflow-x: auto;
}
.preview pre code { background: none; color: inherit; padding: 0; }
.preview blockquote {
border-left: 3px solid var(--brand); margin: 10px 0; padding: 2px 14px; color: var(--text-dim);
}
.preview table { border-collapse: collapse; width: 100%; margin: 10px 0; font-size: 13px; }
.preview th, .preview td { border: 1px solid var(--border); padding: 6px 10px; text-align: left; }
.preview th { background: var(--brand-light); }
.preview img { max-width: 100%; border-radius: 6px; }
.preview a { color: var(--brand); }
#toast {
position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%);
background: #2B2B2B; color: #fff; padding: 10px 20px; border-radius: 8px;
font-size: 13px; opacity: 0; pointer-events: none; transition: .25s; z-index: 999;
}
#toast.show { opacity: 1; }
#toast.err { background: var(--danger); }
</style>
</head> </head>
<body> <body>
<!-- ==================== 登录 ==================== --> <!-- ==================== 登录 ==================== -->
<div id="login-view"> <div id="login-view">
<div class="login-box"> <div class="login-box">
<h1>笔记管理</h1> <h1>强宝小助手</h1>
<p class="sub">使用手机端同一个账号登录</p> <p class="sub">强宝管理小助手</p>
<div class="field"> <div class="field">
<label>用户名</label> <label>用户名</label>
<input id="login-username" autocomplete="username" placeholder="用户名"> <input id="login-username" autocomplete="username" placeholder="用户名">
@@ -197,31 +26,73 @@
</div> </div>
</div> </div>
<!-- ==================== 主界面 ==================== --> <!-- ==================== 主界面 ====================
三层结构:
顶栏 —— 系统级,只放品牌和用户操作(跨模块的东西才配放这儿)
模块菜单 —— 左侧,以后加 Agent 等模块直接往这里塞
模块面板 —— 当前模块自己的工具栏、侧栏和内容
-->
<div id="app-view" style="display:none"> <div id="app-view" style="display:none">
<header>
<h1>笔记管理</h1> <header class="topbar">
<div class="search"><input id="search" placeholder="搜索标题和正文…"></div> <div class="brand"><span class="brand-icon">🐻</span>强宝小助手</div>
<div class="spacer"></div> <div class="spacer"></div>
<span class="who" id="who"></span> <span class="who" id="who"></span>
<button id="new-btn" class="primary">+ 新建</button>
<button id="logout-btn">退出</button> <button id="logout-btn">退出</button>
</header> </header>
<div class="layout"> <div class="console">
<aside class="tags">
<h3>标签</h3>
<div id="tag-list"></div>
</aside>
<main> <nav class="module-nav">
<div id="dropzone"> <button class="module-item active" data-module="notes">
把 <b>.md</b> 文件拖到这里批量导入,或 <a href="#" id="pick-files">点击选择文件</a> <span class="mi-icon">📝</span>
<input type="file" id="file-input" accept=".md,.markdown,.txt" multiple style="display:none"> <span class="mi-text">笔记管理</span>
</button>
<!-- 以后的模块(Agent、数据看板…)往这里加 -->
</nav>
<section class="module-panel">
<div class="toolbar">
<input id="search" placeholder="搜索标题和正文…">
<select id="scope" title="搜索范围">
<option value="current" selected>当前目录</option>
<option value="all">全部笔记</option>
</select>
<select id="sort" title="排序方式">
<option value="updated">最近更新</option>
<option value="created">创建时间</option>
<option value="title">标题</option>
</select>
<div class="spacer"></div>
<button id="new-folder-btn">+ 新建目录</button>
<button id="new-btn" class="primary">+ 新建笔记</button>
</div> </div>
<div id="note-list"></div>
<button id="loadmore" style="display:none">加载更多</button> <div class="module-body">
</main>
<aside class="sidebar">
<div id="folder-tree"></div>
<div class="side-divider"></div>
<div class="side-title">标签</div>
<div id="tag-list"></div>
</aside>
<main class="content">
<div class="breadcrumb" id="breadcrumb"></div>
<div id="dropzone">
把 <b>.md</b> 文件拖到这里批量导入<span id="dropzone-hint"></span>,或 <a href="#" id="pick-files">点击选择文件</a>
<input type="file" id="file-input" accept=".md,.markdown,.txt" multiple style="display:none">
</div>
<div id="note-list"></div>
<button id="loadmore" style="display:none">加载更多</button>
</main>
</div>
</section>
</div> </div>
</div> </div>
@@ -233,418 +104,33 @@
<input class="tags" id="ed-tags" placeholder="标签,逗号分隔"> <input class="tags" id="ed-tags" placeholder="标签,逗号分隔">
</div> </div>
<div class="editor-body"> <div class="editor-body">
<textarea id="ed-content" placeholder="在这里写 Markdown…"></textarea> <div id="vditor"></div>
<div class="preview" id="ed-preview"></div>
</div> </div>
<div class="editor-foot"> <div class="editor-foot">
<span class="hint" id="ed-hint"></span> <span class="hint" id="ed-hint"></span>
<button id="ed-upload">插入图片</button>
<input type="file" id="ed-image" accept="image/*" style="display:none">
<button id="ed-cancel">取消</button> <button id="ed-cancel">取消</button>
<button class="primary" id="ed-save">保存</button> <button class="primary" id="ed-save">保存 (Ctrl+S)</button>
</div>
</div>
</div>
<!-- ==================== 目录名输入 / 目录选择弹窗 ==================== -->
<div id="dialog">
<div class="dialog-box">
<h3 id="dialog-title">新建目录</h3>
<input id="dialog-input" placeholder="目录名">
<select id="dialog-select" style="display:none"></select>
<div class="dialog-foot">
<button id="dialog-cancel">取消</button>
<button class="primary" id="dialog-ok">确定</button>
</div> </div>
</div> </div>
</div> </div>
<div id="toast"></div> <div id="toast"></div>
<script src="https://cdn.jsdelivr.net/npm/marked@12/marked.min.js"></script> <!-- Vditor:本地托管,不依赖任何外部 CDN -->
<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"></script> <script src="/admin/vendor/vditor/dist/index.min.js"></script>
<script> <script src="/admin/admin.js"></script>
(function () {
'use strict';
var API = '/api';
var TOKEN_KEY = 'aq_note_admin_token';
var USER_KEY = 'aq_note_admin_user';
var state = {
token: localStorage.getItem(TOKEN_KEY) || '',
username: localStorage.getItem(USER_KEY) || '',
page: 1,
size: 20,
keyword: '',
tag: '',
total: 0,
editingId: null
};
// ---------------------------------------------------------------- 工具
function $(id) { return document.getElementById(id); }
function esc(s) {
return String(s == null ? '' : s)
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}
function toast(msg, isError) {
var el = $('toast');
el.textContent = msg;
el.className = (isError ? 'err ' : '') + 'show';
clearTimeout(el._t);
el._t = setTimeout(function () { el.className = ''; }, 2400);
}
function formatTime(s) {
if (!s) return '';
return String(s).replace('T', ' ').substring(0, 16);
}
/** 统一的请求封装,带 token 和 401 处理 */
function request(path, options) {
options = options || {};
var headers = options.headers || {};
if (state.token) headers['Authorization'] = 'Bearer ' + state.token;
if (options.body && !(options.body instanceof FormData)) {
headers['Content-Type'] = 'application/json';
}
return fetch(API + path, {
method: options.method || 'GET',
headers: headers,
body: options.body
}).then(function (res) {
if (res.status === 401 || res.status === 403) {
doLogout();
throw new Error('登录已过期,请重新登录');
}
var ct = res.headers.get('content-type') || '';
var parsed = ct.indexOf('application/json') >= 0 ? res.json() : res.text();
return parsed.then(function (data) {
if (!res.ok) {
var msg = (data && (data.message || data.error)) || ('请求失败 ' + res.status);
throw new Error(msg);
}
return data;
});
});
}
// ---------------------------------------------------------------- 登录
function showApp() {
$('login-view').style.display = 'none';
$('app-view').style.display = '';
$('who').textContent = state.username ? ('当前:' + state.username) : '';
state.page = 1;
state.keyword = '';
state.tag = '';
$('search').value = '';
loadTags();
loadNotes(true);
}
function doLogout() {
state.token = '';
state.username = '';
localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(USER_KEY);
$('app-view').style.display = 'none';
$('login-view').style.display = 'flex';
$('note-list').innerHTML = '';
$('tag-list').innerHTML = '';
}
function doLogin() {
var username = $('login-username').value.trim();
var password = $('login-password').value;
if (!username || !password) { toast('请填写用户名和密码', true); return; }
fetch(API + '/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: username, password: password })
}).then(function (res) {
return res.json().then(function (data) {
if (!res.ok || !data.token) {
throw new Error(data.message || data.error || '用户名或密码错误');
}
return data;
});
}).then(function (data) {
state.token = data.token;
state.username = data.username || username;
localStorage.setItem(TOKEN_KEY, state.token);
localStorage.setItem(USER_KEY, state.username);
$('login-password').value = '';
showApp();
}).catch(function (e) {
toast(e.message, true);
});
}
// ---------------------------------------------------------------- 列表
function loadNotes(reset) {
if (reset) { state.page = 1; }
var qs = '?page=' + state.page + '&size=' + state.size;
if (state.keyword) qs += '&keyword=' + encodeURIComponent(state.keyword);
if (state.tag) qs += '&tag=' + encodeURIComponent(state.tag);
request('/notes' + qs).then(function (data) {
state.total = data.total;
renderNotes(data.list, reset);
$('loadmore').style.display = data.hasMore ? 'block' : 'none';
if (data.list.length) state.page++;
}).catch(function (e) { toast(e.message, true); });
}
function renderNotes(list, reset) {
var box = $('note-list');
if (reset) {
if (!list.length) {
box.innerHTML = '<div class="empty">' +
(state.keyword || state.tag ? '没有匹配的笔记' : '还没有笔记,拖个 .md 文件进来试试') +
'</div>';
return;
}
box.innerHTML = '';
}
list.forEach(function (n) { box.appendChild(noteCard(n)); });
}
function noteCard(n) {
var el = document.createElement('div');
el.className = 'note-card';
var tags = (n.tagList || []).map(function (t) {
return '<span class="tag">' + esc(t) + '</span>';
}).join('');
el.innerHTML =
'<div class="head">' +
'<h3>' + esc(n.title) + '</h3>' +
(n.isPinned ? '<span class="pin">📌</span>' : '') +
'</div>' +
'<div class="summary">' + esc(n.summary || '(空笔记)') + '</div>' +
'<div class="meta">' + tags +
'<span class="time">' + esc(formatTime(n.updateTime)) + '</span>' +
'<span class="actions">' +
'<button data-act="pin">' + (n.isPinned ? '取消置顶' : '置顶') + '</button>' +
'<button data-act="edit">编辑</button>' +
'<button class="danger" data-act="del">删除</button>' +
'</span>' +
'</div>';
el.querySelector('[data-act="edit"]').onclick = function () { openEditor(n.id); };
el.querySelector('[data-act="del"]').onclick = function () { removeNote(n); };
el.querySelector('[data-act="pin"]').onclick = function () { togglePin(n); };
return el;
}
function removeNote(n) {
if (!confirm('确定删除「' + n.title + '」?')) return;
request('/notes/' + n.id, { method: 'DELETE' })
.then(function () { toast('已删除'); loadTags(); loadNotes(true); })
.catch(function (e) { toast(e.message, true); });
}
function togglePin(n) {
// 后端 update 是部分更新语义:只发 isPinned,正文不会被覆盖
request('/notes/' + n.id, {
method: 'PUT',
body: JSON.stringify({ isPinned: n.isPinned ? 0 : 1 })
}).then(function () { loadNotes(true); })
.catch(function (e) { toast(e.message, true); });
}
function loadTags() {
request('/notes/tags').then(function (tags) {
var box = $('tag-list');
box.innerHTML = '';
var all = document.createElement('button');
all.className = 'tag-chip' + (state.tag === '' ? ' active' : '');
all.textContent = '全部';
all.onclick = function () { state.tag = ''; loadTags(); loadNotes(true); };
box.appendChild(all);
tags.forEach(function (t) {
var b = document.createElement('button');
b.className = 'tag-chip' + (state.tag === t ? ' active' : '');
b.textContent = t;
b.title = t;
b.onclick = function () { state.tag = t; loadTags(); loadNotes(true); };
box.appendChild(b);
});
}).catch(function () { /* 标签加载失败不影响主流程 */ });
}
// ---------------------------------------------------------------- 编辑器
function renderPreview() {
var md = $('ed-content').value;
var box = $('ed-preview');
if (typeof marked === 'undefined') {
// CDN 不可用时的降级:原样显示,至少不白屏
box.innerHTML = '<pre style="background:none;color:inherit;padding:0">' + esc(md) + '</pre>';
return;
}
var html = marked.parse(md);
box.innerHTML = (typeof DOMPurify !== 'undefined') ? DOMPurify.sanitize(html) : html;
}
function openEditor(id) {
state.editingId = id || null;
$('ed-hint').textContent = id ? '编辑已有笔记' : '新建笔记';
if (!id) {
$('ed-title').value = '';
$('ed-tags').value = '';
$('ed-content').value = '';
renderPreview();
$('editor').classList.add('open');
$('ed-title').focus();
return;
}
request('/notes/' + id).then(function (n) {
$('ed-title').value = n.title || '';
$('ed-tags').value = (n.tagList || []).join(',');
$('ed-content').value = n.content || '';
renderPreview();
$('editor').classList.add('open');
}).catch(function (e) { toast(e.message, true); });
}
function closeEditor() {
$('editor').classList.remove('open');
state.editingId = null;
}
function saveNote() {
var payload = {
title: $('ed-title').value,
content: $('ed-content').value,
tags: $('ed-tags').value,
isPinned: 0
};
var req = state.editingId
? request('/notes/' + state.editingId, { method: 'PUT', body: JSON.stringify(payload) })
: request('/notes', { method: 'POST', body: JSON.stringify(payload) });
req.then(function () {
toast('已保存');
closeEditor();
loadTags();
loadNotes(true);
}).catch(function (e) { toast(e.message, true); });
}
// ---------------------------------------------------------------- 批量导入
function importFiles(files) {
var list = Array.prototype.slice.call(files).filter(function (f) {
return /\.(md|markdown|txt)$/i.test(f.name);
});
if (!list.length) { toast('没有找到 .md 文件', true); return; }
Promise.all(list.map(function (f) {
return new Promise(function (resolve) {
var reader = new FileReader();
reader.onload = function () {
var text = String(reader.result || '');
var firstLine = '';
text.split(/\r?\n/).some(function (line) {
var l = line.replace(/^\s*#{1,6}\s*/, '').trim();
if (l) { firstLine = l; return true; }
return false;
});
resolve({
title: firstLine,
content: text,
sourcePath: f.name,
tags: ''
});
};
reader.readAsText(f, 'utf-8');
});
})).then(function (notes) {
return request('/notes/import', {
method: 'POST',
body: JSON.stringify({ notes: notes })
});
}).then(function (res) {
toast('成功导入 ' + (res.imported || list.length) + ' 篇笔记');
loadTags();
loadNotes(true);
}).catch(function (e) {
toast('导入失败:' + e.message, true);
});
}
// ---------------------------------------------------------------- 图片上传
function uploadImage(file) {
var fd = new FormData();
fd.append('file', file);
request('/notes/attachments', { method: 'POST', body: fd })
.then(function (res) {
var ta = $('ed-content');
var snippet = '![](' + res.url + ')';
var start = ta.selectionStart || 0;
ta.value = ta.value.slice(0, start) + snippet + ta.value.slice(ta.selectionEnd || start);
ta.selectionStart = ta.selectionEnd = start + snippet.length;
ta.focus();
renderPreview();
toast('图片已插入');
})
.catch(function (e) { toast('上传失败:' + e.message, true); });
}
// ---------------------------------------------------------------- 事件绑定
$('login-btn').onclick = doLogin;
$('login-password').onkeydown = function (e) { if (e.key === 'Enter') doLogin(); };
$('login-username').onkeydown = function (e) { if (e.key === 'Enter') $('login-password').focus(); };
$('logout-btn').onclick = doLogout;
$('new-btn').onclick = function () { openEditor(null); };
var searchTimer = null;
$('search').oninput = function () {
clearTimeout(searchTimer);
var v = this.value.trim();
searchTimer = setTimeout(function () { state.keyword = v; loadNotes(true); }, 350);
};
$('loadmore').onclick = function () { loadNotes(false); };
$('pick-files').onclick = function (e) { e.preventDefault(); $('file-input').click(); };
$('file-input').onchange = function () { importFiles(this.files); this.value = ''; };
var dz = $('dropzone');
['dragenter', 'dragover'].forEach(function (ev) {
dz.addEventListener(ev, function (e) { e.preventDefault(); dz.classList.add('over'); });
});
['dragleave', 'drop'].forEach(function (ev) {
dz.addEventListener(ev, function (e) { e.preventDefault(); dz.classList.remove('over'); });
});
dz.addEventListener('drop', function (e) {
if (e.dataTransfer && e.dataTransfer.files) importFiles(e.dataTransfer.files);
});
$('ed-content').oninput = renderPreview;
$('ed-cancel').onclick = closeEditor;
$('ed-save').onclick = saveNote;
$('ed-upload').onclick = function () { $('ed-image').click(); };
$('ed-image').onchange = function () {
if (this.files && this.files[0]) uploadImage(this.files[0]);
this.value = '';
};
$('editor').onclick = function (e) { if (e.target === this) closeEditor(); };
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && $('editor').classList.contains('open')) closeEditor();
if ((e.ctrlKey || e.metaKey) && e.key === 's' && $('editor').classList.contains('open')) {
e.preventDefault(); saveNote();
}
});
// ---------------------------------------------------------------- 启动
if (state.token) {
// 用一次轻量请求验证本地 token 还有效
request('/notes?page=1&size=1')
.then(showApp)
.catch(function () { doLogout(); });
} else {
doLogout();
}
})();
</script>
</body> </body>
</html> </html>
@@ -0,0 +1,220 @@
/*!
* Vditor - A markdown editor written in TypeScript.
*
* MIT License
*
* Copyright (c) 2018-present B3log 开源, b3log.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
.vditor-reset {
color: rgba(0, 0, 0, .85);
font-size: 14px;
line-height: 2;
--callout-note-color: #0969da;
--callout-note-background-color: rgba(9, 105, 218, 0.08);
--callout-tip-color: #1a7f37;
--callout-tip-background-color: rgba(26, 127, 55, 0.08);
--callout-important-color: #8250df;
--callout-important-background-color: rgba(130, 80, 223, 0.08);
--callout-warning-color: #9a6700;
--callout-warning-background-color: rgba(154, 103, 0, 0.08);
--callout-caution-color: #cf222e;
--callout-caution-background-color: rgba(207, 34, 46, 0.08);
}
.vditor-reset img {
max-width: calc(100% - 32px);
}
.vditor-reset p > img {
margin: 34px 0;
box-shadow: 0 8px 20px rgba(143, 168, 191, 0.35);
}
.vditor-reset h1 {
margin-bottom: 20px;
color: rgba(0, 0, 0, .85);
font-weight: 500;
font-size: 30px;
font-family: Avenir, -apple-system, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji, sans-serif;
line-height: 38px
}
.vditor-reset h2 {
font-size: 24px;
line-height: 32px;
}
.vditor-reset h2,
.vditor-reset h3,
.vditor-reset h4,
.vditor-reset h5,
.vditor-reset h6 {
clear: both;
margin: 1.6em 0 .6em;
color: rgba(0, 0, 0, .85);
font-weight: 500;
font-family: Avenir, -apple-system, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji, sans-serif
}
.vditor-reset h3 {
font-size: 18px;
}
.vditor-reset h4 {
font-size: 16px;
}
.vditor-reset h5 {
font-size: 14px;
}
.vditor-reset h6 {
font-size: 12px;
}
.vditor-reset hr {
clear: both;
height: 1px;
margin: 56px 0;
background: #f0f0f0;
border: 0;
}
.vditor-reset p,
.vditor-reset pre {
margin: 1em 0;
}
.vditor-reset ul > li {
margin-left: 20px;
padding-left: 4px;
list-style-type: circle;
}
.vditor-reset ol > li {
margin-left: 20px;
padding-left: 4px;
list-style-type: decimal;
}
.vditor-reset ul > li > p,
.vditor-reset ol > li > p {
margin: 0.2em 0;
}
.vditor-reset code {
margin: 0 1px;
padding: .2em .4em;
font-size: .9em;
border-radius: 3px;
border: 1px solid #f0f0f0;
font-family: sfmono-regular, Consolas, liberation mono, Menlo, Courier, monospace;
}
.vditor-reset code:not(.hljs):not(.highlight-chroma) {
background: #f2f4f5;
color: rgba(0, 0, 0, .65);
}
.vditor-reset pre {
font-family: sfmono-regular, Consolas, liberation mono, Menlo, Courier, monospace;
border-radius: 2px;
}
.vditor-reset .language-abc svg,
.vditor-reset .language-abc path {
fill: currentColor;
color: rgba(0, 0, 0, .85);
}
.vditor-reset .language-graphviz polygon {
fill: transparent;
}
.vditor-reset strong,
.vditor-reset b {
font-weight: 500;
}
.vditor-reset > table {
width: 100%;
margin: 8px 0 16px;
direction: ltr;
empty-cells: show;
border: 1px solid #f0f0f0;
border-collapse: collapse;
border-spacing: 0
}
.vditor-reset > table th {
color: #5c6b77;
font-weight: 500;
white-space: nowrap;
background: rgba(0, 0, 0, .02)
}
.vditor-reset > table th, .vditor-reset > table td {
padding: 16px 24px;
text-align: left;
border: 1px solid #f0f0f0
}
.vditor-reset blockquote {
margin: 1em 0;
padding-left: .8em;
color: rgba(0, 0, 0, .45);
font-size: 90%;
border-left: 4px solid #f0f0f0
}
.vditor-reset blockquote p {
margin: 0;
}
.vditor-reset .vditor-anchor {
margin-left: 8px;
opacity: 0;
transition: opacity 0.3s;
}
.vditor-reset h1:hover .vditor-anchor,
.vditor-reset h2:hover .vditor-anchor,
.vditor-reset h3:hover .vditor-anchor,
.vditor-reset h4:hover .vditor-anchor,
.vditor-reset h5:hover .vditor-anchor,
.vditor-reset h6:hover .vditor-anchor {
display: inline-block;
opacity: 1;
}
.vditor-reset > br,
.vditor-reset > p > br {
clear: both;
}
.vditor-reset a, .vditor-ir__link {
color: #1890ff;
text-decoration: none;
outline: none;
cursor: pointer;
}
@@ -0,0 +1,133 @@
/*!
* Vditor - A markdown editor written in TypeScript.
*
* MIT License
*
* Copyright (c) 2018-present B3log 开源, b3log.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
.vditor-reset {
color: #d1d5da;
--callout-note-color: #58a6ff;
--callout-note-background-color: rgba(56, 139, 253, 0.15);
--callout-tip-color: #3fb950;
--callout-tip-background-color: rgba(46, 160, 67, 0.15);
--callout-important-color: #a371f7;
--callout-important-background-color: rgba(163, 113, 247, 0.15);
--callout-warning-color: #d29922;
--callout-warning-background-color: rgba(187, 128, 9, 0.15);
--callout-caution-color: #f85149;
--callout-caution-background-color: rgba(248, 81, 73, 0.15);
}
.vditor-reset a, .vditor-ir__link {
color: #4285f4;
}
.vditor-reset h1, .vditor-reset h2 {
padding-bottom: 0.3em;
border-bottom: 1px solid #d1d5da
}
.vditor-reset hr {
background-color: #d1d5da
}
.vditor-reset blockquote {
padding: 0 1em;
color: #b9b9b9;
border-left: .25em solid #d1d5da
}
.vditor-reset iframe {
border: 1px solid #141414
}
.vditor-reset table tr {
background-color: #2f363d
}
.vditor-reset table td, .vditor-reset table th {
border: 1px solid #dfe2e5
}
.vditor-reset table tbody tr:nth-child(2n) {
background-color: #24292e
}
.vditor-reset code:not(.hljs):not(.highlight-chroma) {
background-color: rgba(66, 133, 244, .36);
}
.vditor-reset .language-abc svg,
.vditor-reset .language-abc path {
fill: currentColor;
color: #d1d5da;
}
.language-graphviz polygon {
fill: rgba(66, 133, 244, .36);
}
.vditor-reset kbd {
color: #d1d5da;
background-color: #2f363d;
border: 1px solid #141414;
box-shadow: inset 0 -1px 0 #141414
}
.vditor-copy svg {
color: #b9b9b9
}
.vditor-speech {
background-color: #1d2125;
border: 1px solid #141414;
color: #b9b9b9
}
.vditor-speech--current, .vditor-speech:hover {
color: #fff
}
.vditor-linkcard a {
background-color: #1d2125;
}
.vditor-linkcard a:visited .vditor-linkcard__abstract {
color: hsla(0, 0%, 72.5%, .36)
}
.vditor-linkcard__title {
color: #d1d5da
}
.vditor-linkcard__abstract {
color: #b9b9b9
}
.vditor-linkcard__site {
color: #fff
}
.vditor-linkcard__image {
background-color: hsla(0, 0%, 72.5%, .36)
}
@@ -0,0 +1,114 @@
/*!
* Vditor - A markdown editor written in TypeScript.
*
* MIT License
*
* Copyright (c) 2018-present B3log 开源, b3log.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
.vditor-reset {
--callout-note-color: #0969da;
--callout-note-background-color: rgba(9, 105, 218, 0.08);
--callout-tip-color: #1a7f37;
--callout-tip-background-color: rgba(26, 127, 55, 0.08);
--callout-important-color: #8250df;
--callout-important-background-color: rgba(130, 80, 223, 0.08);
--callout-warning-color: #9a6700;
--callout-warning-background-color: rgba(154, 103, 0, 0.08);
--callout-caution-color: #cf222e;
--callout-caution-background-color: rgba(207, 34, 46, 0.08);
}
.vditor-reset h1, .vditor-reset h2 {
padding-bottom: 0.3em;
border-bottom: 1px solid #eaecef;
}
.vditor-reset hr {
background-color: #eaecef;
}
.vditor-reset blockquote {
color: #6a737d;
border-left: .25em solid #eaecef
}
.vditor-reset iframe {
border: 1px solid #d1d5da
}
.vditor-reset table tr {
border-top: 1px solid #c6cbd1;
background-color: #fafbfc
}
.vditor-reset table td, .vditor-reset table th {
border: 1px solid #dfe2e5
}
.vditor-reset table tbody tr:nth-child(2n) {
background-color: #fff
}
.vditor-reset code:not(.hljs):not(.highlight-chroma) {
background-color: rgba(27, 31, 35, .05);
}
.vditor-reset kbd {
color: #24292e;
background-color: #fafbfc;
border: solid 1px #d1d5da;
box-shadow: inset 0 -1px 0 #d1d5da;
}
.vditor-speech {
background-color: #f6f8fa;
border: 1px solid #d1d5da;
color: #586069;
}
.vditor-speech--current, .vditor-speech:hover {
color: #4285f4;
}
.vditor-linkcard a {
background-color: #f6f8fa;
}
.vditor-linkcard a:visited .vditor-linkcard__abstract {
color: rgba(88, 96, 105, 0.36);
}
.vditor-linkcard__title {
color: #24292e;
}
.vditor-linkcard__abstract {
color: #586069;
}
.vditor-linkcard__site {
color: #4285f4;
}
.vditor-linkcard__image {
background-color: rgba(88, 96, 105, 0.36);
}
@@ -0,0 +1,104 @@
/*!
* Vditor - A markdown editor written in TypeScript.
*
* MIT License
*
* Copyright (c) 2018-present B3log 开源, b3log.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
.vditor-reset {
font-family: "mp-quote", -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", "EmojiSymbols";
color: rgb(62, 62, 62);
--callout-note-color: #0969da;
--callout-note-background-color: rgba(9, 105, 218, 0.08);
--callout-tip-color: #1a7f37;
--callout-tip-background-color: rgba(26, 127, 55, 0.08);
--callout-important-color: #8250df;
--callout-important-background-color: rgba(130, 80, 223, 0.08);
--callout-warning-color: #9a6700;
--callout-warning-background-color: rgba(154, 103, 0, 0.08);
--callout-caution-color: #cf222e;
--callout-caution-background-color: rgba(207, 34, 46, 0.08);
}
.vditor-reset a, .vditor-ir__link {
color: #576b95;
}
.vditor-reset h1 {
font-weight: 400;
text-align: center;
color: rgb(26, 173, 25);
font-size: 24px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAAGElEQVQImWNkXs/wn4GKgImahjEwMDAAAA6aAbVUOzXRAAAAAElFTkSuQmCC);
background-repeat: no-repeat;
background-position: center bottom;
}
.vditor-reset h2 {
font-weight: 400;
text-align: center;
font-size: 20px;
}
.vditor-reset h3,
.vditor-reset h4,
.vditor-reset h5,
.vditor-reset h6 {
font-weight: 400;
}
.vditor-reset hr {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
transform-origin: 0 0;
transform: scale(1, 0.5);
height: 0;
}
.vditor-reset blockquote {
padding: 4px 0 0 10px;
border-left: 3px solid #dbdbdb;
color: #9a9a9a;
line-height: 1.6;
font-size: 15px;
margin: 1em 0;
}
.vditor-reset code {
font-size: 14px;
border: 1px solid #f0f0f0;
border-radius: 2px;
}
.vditor-reset code:not(.hljs):not(.highlight-chroma) {
background-color: rgba(0, 0, 0, 0.03);
color: #333;
}
.vditor-reset .language-abc svg,
.vditor-reset .language-abc path {
fill: currentColor;
color: rgb(62, 62, 62);
}
.vditor-reset .language-graphviz polygon {
fill: transparent;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

@@ -0,0 +1 @@
<svg width="160px" height="160px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-double-ring" style="background: none;"><circle cx="50" cy="50" ng-attr-r="{{config.radius}}" ng-attr-stroke-width="{{config.width}}" ng-attr-stroke="{{config.c1}}" ng-attr-stroke-dasharray="{{config.dasharray}}" fill="none" stroke-linecap="round" r="20" stroke-width="4" stroke="#3b3e43" stroke-dasharray="31.41592653589793 31.41592653589793" transform="rotate(111.924 50 50)"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1.5s" begin="0s" repeatCount="indefinite"></animateTransform></circle><circle cx="50" cy="50" ng-attr-r="{{config.radius2}}" ng-attr-stroke-width="{{config.width}}" ng-attr-stroke="{{config.c2}}" ng-attr-stroke-dasharray="{{config.dasharray2}}" ng-attr-stroke-dashoffset="{{config.dashoffset2}}" fill="none" stroke-linecap="round" r="15" stroke-width="4" stroke="#d23f31" stroke-dasharray="23.561944901923447 23.561944901923447" stroke-dashoffset="23.561944901923447" transform="rotate(-111.924 50 50)"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;-360 50 50" keyTimes="0;1" dur="1.5s" begin="0s" repeatCount="indefinite"></animateTransform></circle></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2006, Ivan Sagalaev.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: a11y-dark
Author: @ericwbailey
Maintainer: @ericwbailey
Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css
*/.hljs{background:#2b2b2b;color:#f8f8f2}.hljs-comment,.hljs-quote{color:#d4d0ab}.hljs-deletion,.hljs-name,.hljs-regexp,.hljs-selector-class,.hljs-selector-id,.hljs-tag,.hljs-template-variable,.hljs-variable{color:#ffa07a}.hljs-built_in,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-type{color:#f5ab35}.hljs-attribute{color:gold}.hljs-addition,.hljs-bullet,.hljs-string,.hljs-symbol{color:#abe338}.hljs-section,.hljs-title{color:#00e0e0}.hljs-keyword,.hljs-selector-tag{color:#dcc6e0}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}@media screen and (-ms-high-contrast:active){.hljs-addition,.hljs-attribute,.hljs-built_in,.hljs-bullet,.hljs-comment,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-quote,.hljs-string,.hljs-symbol,.hljs-type{color:highlight}.hljs-keyword,.hljs-selector-tag{font-weight:700}}
@@ -0,0 +1,7 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: a11y-light
Author: @ericwbailey
Maintainer: @ericwbailey
Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css
*/.hljs{background:#fefefe;color:#545454}.hljs-comment,.hljs-quote{color:#696969}.hljs-deletion,.hljs-name,.hljs-regexp,.hljs-selector-class,.hljs-selector-id,.hljs-tag,.hljs-template-variable,.hljs-variable{color:#d91e18}.hljs-attribute,.hljs-built_in,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-type{color:#aa5d00}.hljs-addition,.hljs-bullet,.hljs-string,.hljs-symbol{color:green}.hljs-section,.hljs-title{color:#007faa}.hljs-keyword,.hljs-selector-tag{color:#7928a1}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}@media screen and (-ms-high-contrast:active){.hljs-addition,.hljs-attribute,.hljs-built_in,.hljs-bullet,.hljs-comment,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-quote,.hljs-string,.hljs-symbol,.hljs-type{color:highlight}.hljs-keyword,.hljs-selector-tag{font-weight:700}}
@@ -0,0 +1,20 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: Agate
Author: (c) Taufik Nurrohman <hi@taufik-nurrohman.com>
Maintainer: @taufik-nurrohman
Updated: 2021-04-24
#333
#62c8f3
#7bd694
#888
#a2fca2
#ade5fc
#b8d8a2
#c6b4f0
#d36363
#fc9b9b
#fcc28c
#ffa
#fff
*/.hljs{background:#333;color:#fff}.hljs-doctag,.hljs-meta-keyword,.hljs-name,.hljs-strong{font-weight:700}.hljs-code,.hljs-emphasis{font-style:italic}.hljs-section,.hljs-tag{color:#62c8f3}.hljs-selector-class,.hljs-selector-id,.hljs-template-variable,.hljs-variable{color:#ade5fc}.hljs-meta-string,.hljs-string{color:#a2fca2}.hljs-attr,.hljs-quote,.hljs-selector-attr{color:#7bd694}.hljs-tag .hljs-attr{color:inherit}.hljs-attribute,.hljs-title,.hljs-type{color:#ffa}.hljs-number,.hljs-symbol{color:#d36363}.hljs-bullet,.hljs-template-tag{color:#b8d8a2}.hljs-built_in,.hljs-keyword,.hljs-literal,.hljs-selector-tag{color:#fcc28c}.hljs-code,.hljs-comment,.hljs-formula{color:#888}.hljs-link,.hljs-regexp,.hljs-selector-pseudo{color:#c6b4f0}.hljs-meta{color:#fc9b9b}.hljs-deletion{background:#fc9b9b;color:#333}.hljs-addition{background:#a2fca2;color:#333}.hljs-subst{color:#fff}.hljs a{color:inherit}.hljs a:focus,.hljs a:hover{color:inherit;text-decoration:underline}.hljs mark{background:#555;color:inherit}
@@ -0,0 +1,9 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: An Old Hope – Star Wars Syntax
Author: (c) Gustavo Costa <gusbemacbe@gmail.com>
Maintainer: @gusbemacbe
Original theme - Ocean Dark Theme – by https://github.com/gavsiu
Based on Jesse Leite's Atom syntax theme 'An Old Hope'
https://github.com/JesseLeite/an-old-hope-syntax-atom
*/.hljs{background:#1c1d21;color:#c0c5ce}.hljs-comment,.hljs-quote{color:#b6b18b}.hljs-deletion,.hljs-name,.hljs-regexp,.hljs-selector-class,.hljs-selector-id,.hljs-tag,.hljs-template-variable,.hljs-variable{color:#eb3c54}.hljs-built_in,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-type{color:#e7ce56}.hljs-attribute{color:#ee7c2b}.hljs-addition,.hljs-bullet,.hljs-string,.hljs-symbol{color:#4fb4d7}.hljs-section,.hljs-title{color:#78bb65}.hljs-keyword,.hljs-selector-tag{color:#b45ea4}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#a9b7c6;background:#282b2e}.hljs-bullet,.hljs-literal,.hljs-number,.hljs-symbol{color:#6897bb}.hljs-deletion,.hljs-keyword,.hljs-selector-tag{color:#cc7832}.hljs-link,.hljs-template-variable,.hljs-variable{color:#629755}.hljs-comment,.hljs-quote{color:grey}.hljs-meta{color:#bbb529}.hljs-addition,.hljs-attribute,.hljs-string{color:#6a8759}.hljs-section,.hljs-title,.hljs-type{color:#ffc66d}.hljs-name,.hljs-selector-class,.hljs-selector-id{color:#e8bf6a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
@@ -0,0 +1,84 @@
.hljs {
display: block;
padding: 1em;
overflow-x: auto;
color: rgba(0, 0, 0, .85);
border-radius: 2px;
}
.hljs::selection {
text-shadow: none;
background: #b3d4fc;
}
.hljs-comment,
.hljs-quote {
color: #708090;
font-style: italic;
}
.hljs-doctag,
.hljs-keyword,
.hljs-formula {
color: #008dff;
}
.hljs-section,
.hljs-name,
.hljs-selector-tag,
.hljs-deletion,
.hljs-subst {
color: #999;
}
.hljs-literal {
color: #56b6c2;
}
.hljs-regexp {
color: #e90;
}
.hljs-string,
.hljs-addition,
.hljs-attribute,
.hljs-meta-string {
color: #0b8235;
}
.hljs-built_in,
.hljs-class .hljs-title {
color: #e6c07b;
}
.hljs-attr,
.hljs-variable,
.hljs-template-variable,
.hljs-type,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-number {
color: #f81d22;
}
.hljs-symbol,
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-title {
color: #f81d22;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#fff;color:#434f54}.hljs-subst{color:#434f54}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-name,.hljs-selector-tag{color:#00979d}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-literal{color:#d35400}.hljs-link,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#00979d}.hljs-deletion,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#005c5f}.hljs-comment{color:rgba(149,165,166,.8)}.hljs-meta .hljs-keyword{color:#728e00}.hljs-meta{color:#434f54}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-function{color:#728e00}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-number{color:#8a7b52}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#222;color:#aaa}.hljs-subst{color:#aaa}.hljs-section{color:#fff}.hljs-comment,.hljs-meta,.hljs-quote{color:#444}.hljs-bullet,.hljs-regexp,.hljs-string,.hljs-symbol{color:#fc3}.hljs-addition,.hljs-number{color:#0c6}.hljs-attribute,.hljs-built_in,.hljs-link,.hljs-literal,.hljs-template-variable,.hljs-type{color:#32aaee}.hljs-keyword,.hljs-name,.hljs-selector-class,.hljs-selector-id,.hljs-selector-tag{color:#64a}.hljs-deletion,.hljs-template-tag,.hljs-title,.hljs-variable{color:#b16}.hljs-doctag,.hljs-section,.hljs-strong{font-weight:700}.hljs-emphasis{font-style:italic}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#fff;color:#000}.hljs-addition,.hljs-attribute,.hljs-bullet,.hljs-link,.hljs-section,.hljs-string,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#888}.hljs-comment,.hljs-deletion,.hljs-meta,.hljs-quote{color:#ccc}.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-strong,.hljs-type{font-weight:700}.hljs-emphasis{font-style:italic}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-keyword,.hljs-operator,.hljs-pattern-match{color:#f92672}.hljs-function,.hljs-pattern-match .hljs-constructor{color:#61aeee}.hljs-function .hljs-params{color:#a6e22e}.hljs-function .hljs-params .hljs-typing{color:#fd971f}.hljs-module-access .hljs-module{color:#7e57c2}.hljs-constructor{color:#e2b93d}.hljs-constructor .hljs-string{color:#9ccc65}.hljs-comment,.hljs-quote{color:#b18eb1;font-style:italic}.hljs-doctag,.hljs-formula{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
@@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#383a42;background:#fafafa}.hljs-comment,.hljs-quote{color:#a0a1a7;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#0184bb}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#50a14f}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#4078f2}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#c18401}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
@@ -0,0 +1,7 @@
/*!
Theme: 3024
Author: Jan T. Sott (http://github.com/idleberg)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#a5a2a2;background:#090300}.hljs ::selection,.hljs::selection{background-color:#4a4543;color:#a5a2a2}.hljs-comment{color:#5c5855}.hljs-tag{color:#807d7c}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#a5a2a2}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#db2d20}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#e8bbd0}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#fded02}.hljs-strong{font-weight:700;color:#fded02}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#01a252}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#b5e4f4}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#01a0e4}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#a16a94}.hljs-emphasis{color:#a16a94;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#cdab53}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Apathy
Author: Jannik Siebert (https://github.com/janniks)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#81b5ac;background:#031a16}.hljs ::selection,.hljs::selection{background-color:#184e45;color:#81b5ac}.hljs-comment{color:#2b685e}.hljs-tag{color:#5f9c92}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#81b5ac}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#3e9688}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#3e7996}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#3e4c96}.hljs-strong{font-weight:700;color:#3e4c96}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#883e96}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#963e4c}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#96883e}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#4c963e}.hljs-emphasis{color:#4c963e;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#3e965b}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Apprentice
Author: romainl
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#bcbcbc;background:#262626}.hljs ::selection,.hljs::selection{background-color:#333;color:#bcbcbc}.hljs-comment{color:#6c6c6c}.hljs-tag{color:#787878}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#bcbcbc}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#ff8700}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#5f8787}.hljs-strong{font-weight:700;color:#5f8787}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#87af87}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#5f875f}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#ffffaf}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#87afd7}.hljs-emphasis{color:#87afd7;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#5f87af}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Ashes
Author: Jannik Siebert (https://github.com/janniks)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c7ccd1;background:#1c2023}.hljs ::selection,.hljs::selection{background-color:#565e65;color:#c7ccd1}.hljs-comment{color:#747c84}.hljs-tag{color:#adb3ba}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c7ccd1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#c7ae95}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#c7c795}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#aec795}.hljs-strong{font-weight:700;color:#aec795}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#95c7ae}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#95aec7}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#ae95c7}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#c795ae}.hljs-emphasis{color:#c795ae;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#c79595}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Cave Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#585260;background:#efecf4}.hljs ::selection,.hljs::selection{background-color:#8b8792;color:#585260}.hljs-comment{color:#7e7887}.hljs-tag{color:#655f6d}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#585260}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#be4678}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aa573c}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a06e3b}.hljs-strong{font-weight:700;color:#a06e3b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#2a9292}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#398bc6}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#576ddb}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#955ae7}.hljs-emphasis{color:#955ae7;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#bf40bf}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Cave
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#8b8792;background:#19171c}.hljs ::selection,.hljs::selection{background-color:#585260;color:#8b8792}.hljs-comment{color:#655f6d}.hljs-tag{color:#7e7887}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#8b8792}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#be4678}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aa573c}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a06e3b}.hljs-strong{font-weight:700;color:#a06e3b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#2a9292}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#398bc6}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#576ddb}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#955ae7}.hljs-emphasis{color:#955ae7;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#bf40bf}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Dune Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#6e6b5e;background:#fefbec}.hljs ::selection,.hljs::selection{background-color:#a6a28c;color:#6e6b5e}.hljs-comment{color:#999580}.hljs-tag{color:#7d7a68}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#6e6b5e}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#d73737}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#b65611}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#ae9513}.hljs-strong{font-weight:700;color:#ae9513}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#60ac39}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1fad83}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#6684e1}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#b854d4}.hljs-emphasis{color:#b854d4;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#d43552}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Dune
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#a6a28c;background:#20201d}.hljs ::selection,.hljs::selection{background-color:#6e6b5e;color:#a6a28c}.hljs-comment{color:#7d7a68}.hljs-tag{color:#999580}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#a6a28c}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#d73737}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#b65611}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#ae9513}.hljs-strong{font-weight:700;color:#ae9513}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#60ac39}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1fad83}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#6684e1}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#b854d4}.hljs-emphasis{color:#b854d4;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#d43552}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Estuary Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#5f5e4e;background:#f4f3ec}.hljs ::selection,.hljs::selection{background-color:#929181;color:#5f5e4e}.hljs-comment{color:#878573}.hljs-tag{color:#6c6b5a}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#5f5e4e}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ba6236}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#ae7313}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a5980d}.hljs-strong{font-weight:700;color:#a5980d}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#7d9726}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#5b9d48}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#36a166}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#5f9182}.hljs-emphasis{color:#5f9182;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#9d6c7c}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Estuary
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#929181;background:#22221b}.hljs ::selection,.hljs::selection{background-color:#5f5e4e;color:#929181}.hljs-comment{color:#6c6b5a}.hljs-tag{color:#878573}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#929181}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ba6236}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#ae7313}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a5980d}.hljs-strong{font-weight:700;color:#a5980d}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#7d9726}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#5b9d48}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#36a166}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#5f9182}.hljs-emphasis{color:#5f9182;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#9d6c7c}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Forest Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#68615e;background:#f1efee}.hljs ::selection,.hljs::selection{background-color:#a8a19f;color:#68615e}.hljs-comment{color:#9c9491}.hljs-tag{color:#766e6b}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#68615e}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#f22c40}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#df5320}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#c38418}.hljs-strong{font-weight:700;color:#c38418}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#7b9726}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#3d97b8}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#407ee7}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6666ea}.hljs-emphasis{color:#6666ea;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#c33ff3}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Forest
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#a8a19f;background:#1b1918}.hljs ::selection,.hljs::selection{background-color:#68615e;color:#a8a19f}.hljs-comment{color:#766e6b}.hljs-tag{color:#9c9491}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#a8a19f}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#f22c40}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#df5320}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#c38418}.hljs-strong{font-weight:700;color:#c38418}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#7b9726}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#3d97b8}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#407ee7}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6666ea}.hljs-emphasis{color:#6666ea;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#c33ff3}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Heath Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#695d69;background:#f7f3f7}.hljs ::selection,.hljs::selection{background-color:#ab9bab;color:#695d69}.hljs-comment{color:#9e8f9e}.hljs-tag{color:#776977}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#695d69}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ca402b}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#a65926}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#bb8a35}.hljs-strong{font-weight:700;color:#bb8a35}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#918b3b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#159393}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#516aec}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#7b59c0}.hljs-emphasis{color:#7b59c0;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#c3c}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Heath
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#ab9bab;background:#1b181b}.hljs ::selection,.hljs::selection{background-color:#695d69;color:#ab9bab}.hljs-comment{color:#776977}.hljs-tag{color:#9e8f9e}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#ab9bab}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ca402b}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#a65926}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#bb8a35}.hljs-strong{font-weight:700;color:#bb8a35}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#918b3b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#159393}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#516aec}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#7b59c0}.hljs-emphasis{color:#7b59c0;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#c3c}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Lakeside Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#516d7b;background:#ebf8ff}.hljs ::selection,.hljs::selection{background-color:#7ea2b4;color:#516d7b}.hljs-comment{color:#7195a8}.hljs-tag{color:#5a7b8c}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#516d7b}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#d22d72}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#935c25}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#8a8a0f}.hljs-strong{font-weight:700;color:#8a8a0f}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#568c3b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#2d8f6f}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#257fad}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6b6bb8}.hljs-emphasis{color:#6b6bb8;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#b72dd2}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Lakeside
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#7ea2b4;background:#161b1d}.hljs ::selection,.hljs::selection{background-color:#516d7b;color:#7ea2b4}.hljs-comment{color:#5a7b8c}.hljs-tag{color:#7195a8}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#7ea2b4}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#d22d72}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#935c25}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#8a8a0f}.hljs-strong{font-weight:700;color:#8a8a0f}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#568c3b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#2d8f6f}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#257fad}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6b6bb8}.hljs-emphasis{color:#6b6bb8;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#b72dd2}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Plateau Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#585050;background:#f4ecec}.hljs ::selection,.hljs::selection{background-color:#8a8585;color:#585050}.hljs-comment{color:#7e7777}.hljs-tag{color:#655d5d}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#585050}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ca4949}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#b45a3c}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a06e3b}.hljs-strong{font-weight:700;color:#a06e3b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#4b8b8b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#5485b6}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#7272ca}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#8464c4}.hljs-emphasis{color:#8464c4;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#bd5187}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Plateau
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#8a8585;background:#1b1818}.hljs ::selection,.hljs::selection{background-color:#585050;color:#8a8585}.hljs-comment{color:#655d5d}.hljs-tag{color:#7e7777}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#8a8585}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ca4949}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#b45a3c}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a06e3b}.hljs-strong{font-weight:700;color:#a06e3b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#4b8b8b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#5485b6}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#7272ca}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#8464c4}.hljs-emphasis{color:#8464c4;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#bd5187}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Savanna Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#526057;background:#ecf4ee}.hljs ::selection,.hljs::selection{background-color:#87928a;color:#526057}.hljs-comment{color:#78877d}.hljs-tag{color:#5f6d64}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#526057}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#b16139}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#9f713c}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a07e3b}.hljs-strong{font-weight:700;color:#a07e3b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#489963}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1c9aa0}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#478c90}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#55859b}.hljs-emphasis{color:#55859b;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#867469}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Savanna
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#87928a;background:#171c19}.hljs ::selection,.hljs::selection{background-color:#526057;color:#87928a}.hljs-comment{color:#5f6d64}.hljs-tag{color:#78877d}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#87928a}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#b16139}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#9f713c}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a07e3b}.hljs-strong{font-weight:700;color:#a07e3b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#489963}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1c9aa0}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#478c90}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#55859b}.hljs-emphasis{color:#55859b;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#867469}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Seaside Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#5e6e5e;background:#f4fbf4}.hljs ::selection,.hljs::selection{background-color:#8ca68c;color:#5e6e5e}.hljs-comment{color:#809980}.hljs-tag{color:#687d68}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#5e6e5e}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#e6193c}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#87711d}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#98981b}.hljs-strong{font-weight:700;color:#98981b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#29a329}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1999b3}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#3d62f5}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#ad2bee}.hljs-emphasis{color:#ad2bee;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#e619c3}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Seaside
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#8ca68c;background:#131513}.hljs ::selection,.hljs::selection{background-color:#5e6e5e;color:#8ca68c}.hljs-comment{color:#687d68}.hljs-tag{color:#809980}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#8ca68c}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#e6193c}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#87711d}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#98981b}.hljs-strong{font-weight:700;color:#98981b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#29a329}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1999b3}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#3d62f5}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#ad2bee}.hljs-emphasis{color:#ad2bee;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#e619c3}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Sulphurpool Light
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#5e6687;background:#f5f7ff}.hljs ::selection,.hljs::selection{background-color:#979db4;color:#5e6687}.hljs-comment{color:#898ea4}.hljs-tag{color:#6b7394}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#5e6687}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#c94922}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#c76b29}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#c08b30}.hljs-strong{font-weight:700;color:#c08b30}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#ac9739}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#22a2c9}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#3d8fd1}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6679cc}.hljs-emphasis{color:#6679cc;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#9c637a}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atelier Sulphurpool
Author: Bram de Haan (http://atelierbramdehaan.nl)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#979db4;background:#202746}.hljs ::selection,.hljs::selection{background-color:#5e6687;color:#979db4}.hljs-comment{color:#6b7394}.hljs-tag{color:#898ea4}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#979db4}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#c94922}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#c76b29}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#c08b30}.hljs-strong{font-weight:700;color:#c08b30}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#ac9739}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#22a2c9}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#3d8fd1}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6679cc}.hljs-emphasis{color:#6679cc;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#9c637a}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Atlas
Author: Alex Lende (https://ajlende.com)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#a1a19a;background:#002635}.hljs ::selection,.hljs::selection{background-color:#517f8d;color:#a1a19a}.hljs-comment{color:#6c8b91}.hljs-tag{color:#869696}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#a1a19a}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ff5a67}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#f08e48}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#ffcc1b}.hljs-strong{font-weight:700;color:#ffcc1b}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#7fc06e}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#14747e}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#5dd7b9}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#9a70a4}.hljs-emphasis{color:#9a70a4;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#c43060}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Bespin
Author: Jan T. Sott
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#8a8986;background:#28211c}.hljs ::selection,.hljs::selection{background-color:#5e5d5c;color:#8a8986}.hljs-comment{color:#666}.hljs-tag{color:#797977}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#8a8986}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#cf6a4c}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#cf7d34}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#f9ee98}.hljs-strong{font-weight:700;color:#f9ee98}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#54be0d}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#afc4db}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#5ea6ea}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#9b859d}.hljs-emphasis{color:#9b859d;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#937121}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Bathory)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#e78a53}.hljs-strong{font-weight:700;color:#e78a53}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#fbcb97}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Burzum)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#9ba}.hljs-strong{font-weight:700;color:#9ba}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#dec}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Dark Funeral)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#5f81a5}.hljs-strong{font-weight:700;color:#5f81a5}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#d0dfee}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Gorgoroth)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#8c7f70}.hljs-strong{font-weight:700;color:#8c7f70}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#9b8d7f}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Immortal)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#567}.hljs-strong{font-weight:700;color:#567}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#79b}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Khold)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#974b46}.hljs-strong{font-weight:700;color:#974b46}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#eceee3}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Marduk)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#626b67}.hljs-strong{font-weight:700;color:#626b67}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#a5aaa7}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Mayhem)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#eecc6c}.hljs-strong{font-weight:700;color:#eecc6c}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#f3ecd4}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Nile)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#775}.hljs-strong{font-weight:700;color:#775}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#a98}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal (Venom)
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#79241f}.hljs-strong{font-weight:700;color:#79241f}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#f8f7f2}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Black Metal
Author: metalelf0 (https://github.com/metalelf0)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c1c1;background:#000}.hljs ::selection,.hljs::selection{background-color:#222;color:#c1c1c1}.hljs-comment{color:#333}.hljs-tag{color:#999}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c1c1}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#5f8787}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#aaa}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#a06666}.hljs-strong{font-weight:700;color:#a06666}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#d99}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#aaa}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#888}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#999}.hljs-emphasis{color:#999;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#444}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Brewer
Author: Timothée Poisot (http://github.com/tpoisot)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#b7b8b9;background:#0c0d0e}.hljs ::selection,.hljs::selection{background-color:#515253;color:#b7b8b9}.hljs-comment{color:#737475}.hljs-tag{color:#959697}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#b7b8b9}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#e31a1c}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#e6550d}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#dca060}.hljs-strong{font-weight:700;color:#dca060}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#31a354}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#80b1d3}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#3182bd}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#756bb1}.hljs-emphasis{color:#756bb1;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#b15928}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Bright
Author: Chris Kempson (http://chriskempson.com)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#e0e0e0;background:#000}.hljs ::selection,.hljs::selection{background-color:#505050;color:#e0e0e0}.hljs-comment{color:#b0b0b0}.hljs-tag{color:#d0d0d0}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#e0e0e0}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#fb0120}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#fc6d24}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#fda331}.hljs-strong{font-weight:700;color:#fda331}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#a1c659}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#76c7b7}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#6fb3d2}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#d381c3}.hljs-emphasis{color:#d381c3;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#be643c}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
@@ -0,0 +1,7 @@
/*!
Theme: Brogrammer
Author: Vik Ramanujam (http://github.com/piggyslasher)
License: ~ MIT (or more permissive) [via base16-schemes-source]
Maintainer: @highlightjs/core-team
Version: 2021.09.0
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#4e5ab7;background:#1f1f1f}.hljs ::selection,.hljs::selection{background-color:#2dc55e;color:#4e5ab7}.hljs-comment{color:#ecba0f}.hljs-tag{color:#2a84d2}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#4e5ab7}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#d6dbe5}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#de352e}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#1dd361}.hljs-strong{font-weight:700;color:#1dd361}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#f3bd09}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#1081d6}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#5350b9}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#0f7ddb}.hljs-emphasis{color:#0f7ddb;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#fff}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}

Some files were not shown because too many files have changed in this diff Show More