MD编辑器更新
UI更新
@@ -1,6 +1,7 @@
|
||||
package com.accounting.controller;
|
||||
|
||||
import com.accounting.dto.NoteAttachmentResponse;
|
||||
import com.accounting.dto.NoteFolderAssignRequest;
|
||||
import com.accounting.dto.NoteImportRequest;
|
||||
import com.accounting.dto.NotePageResponse;
|
||||
import com.accounting.dto.NoteRequest;
|
||||
@@ -45,10 +46,14 @@ public class NoteController {
|
||||
@RequestParam(defaultValue = "20") int size,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String tag,
|
||||
@RequestParam(defaultValue = "all") String scope,
|
||||
@RequestParam(required = false) Long folderId,
|
||||
@RequestParam(defaultValue = "updated") String sort,
|
||||
Authentication 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 = "查询笔记详情(含正文)")
|
||||
@@ -94,7 +99,7 @@ public class NoteController {
|
||||
Authentication 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<>();
|
||||
result.put("success", true);
|
||||
@@ -102,6 +107,21 @@ public class NoteController {
|
||||
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 中引用的地址")
|
||||
@PostMapping("/attachments")
|
||||
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
|
||||
private List<Item> notes;
|
||||
|
||||
/** 导入到哪个目录;null = 未分类。由前端按当前所在目录传入 */
|
||||
private Long folderId;
|
||||
|
||||
@Data
|
||||
public static class Item {
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ public class NoteListItem {
|
||||
|
||||
private Long id;
|
||||
|
||||
/** 所属目录 ID,null = 未分类 */
|
||||
private Long folderId;
|
||||
|
||||
private String title;
|
||||
|
||||
/** 摘要,由正文自动提取 */
|
||||
|
||||
@@ -13,6 +13,9 @@ public class NoteResponse {
|
||||
|
||||
private Long id;
|
||||
|
||||
/** 所属目录 ID,null = 未分类 */
|
||||
private Long folderId;
|
||||
|
||||
private String title;
|
||||
|
||||
private String content;
|
||||
|
||||
@@ -24,6 +24,9 @@ public class Note {
|
||||
|
||||
private Long userId;
|
||||
|
||||
/** 所属目录 ID,null = 未分类 */
|
||||
private Long folderId;
|
||||
|
||||
private String title;
|
||||
|
||||
/** 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.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
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
|
||||
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.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;
|
||||
@@ -19,6 +20,7 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -28,6 +30,16 @@ public class NoteService {
|
||||
@Autowired
|
||||
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;
|
||||
|
||||
@@ -55,14 +67,18 @@ public class NoteService {
|
||||
/**
|
||||
* 分页查询笔记列表(不含正文)
|
||||
*
|
||||
* @param scope all(默认,全部笔记)/ uncategorized(未分类)/ folder(指定目录)
|
||||
* @param folderId 仅 scope=folder 时有意义,查询含该目录及其所有子目录
|
||||
* @param keyword 关键词,同时匹配标题和正文,可为空
|
||||
* @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 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;
|
||||
if (total == 0) {
|
||||
@@ -70,9 +86,7 @@ public class NoteService {
|
||||
} else {
|
||||
int offset = (safePage - 1) * safeSize;
|
||||
rows = noteMapper.selectList(
|
||||
buildListWrapper(userId, keyword, tag)
|
||||
.orderByDesc(Note::getIsPinned)
|
||||
.orderByDesc(Note::getUpdateTime)
|
||||
applySort(buildListWrapper(userId, scope, folderId, keyword, tag), sort)
|
||||
// 项目里没有配置 MyBatis-Plus 的 PaginationInnerInterceptor,
|
||||
// selectPage 不会真正生成 LIMIT,所以这里直接拼。
|
||||
// offset/size 都是上面校验过的 int,不存在注入问题。
|
||||
@@ -180,16 +194,39 @@ public class NoteService {
|
||||
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 实际写入的条数
|
||||
*/
|
||||
@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()) {
|
||||
return 0;
|
||||
}
|
||||
folderService.requireOwnedIfPresent(userId, folderId);
|
||||
|
||||
int count = 0;
|
||||
for (NoteImportRequest.Item item : items) {
|
||||
@@ -197,6 +234,7 @@ public class NoteService {
|
||||
|
||||
Note note = new Note();
|
||||
note.setUserId(userId);
|
||||
note.setFolderId(folderId);
|
||||
note.setTitle(resolveTitle(item.getTitle(), content, item.getSourcePath()));
|
||||
note.setContent(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>()
|
||||
.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)) {
|
||||
String kw = keyword.trim();
|
||||
wrapper.and(q -> q.like(Note::getTitle, kw).or().like(Note::getContent, kw));
|
||||
@@ -230,6 +284,25 @@ public class NoteService {
|
||||
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) {
|
||||
NoteListItem item = new NoteListItem();
|
||||
item.setId(note.getId());
|
||||
item.setFolderId(note.getFolderId());
|
||||
item.setTitle(note.getTitle());
|
||||
item.setSummary(note.getSummary());
|
||||
item.setTagList(parseTags(note.getTags()));
|
||||
@@ -341,6 +415,7 @@ public class NoteService {
|
||||
private NoteResponse toResponse(Note note) {
|
||||
NoteResponse response = new NoteResponse();
|
||||
response.setId(note.getId());
|
||||
response.setFolderId(note.getFolderId());
|
||||
response.setTitle(note.getTitle());
|
||||
response.setContent(note.getContent());
|
||||
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;
|
||||
@@ -123,10 +123,26 @@ CREATE TABLE IF NOT EXISTS `gold_price` (
|
||||
INDEX `idx_gold_date` (`gold_id`, `price_date`) 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` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '笔记ID',
|
||||
`user_id` BIGINT NOT NULL COMMENT '用户ID',
|
||||
`folder_id` BIGINT DEFAULT NULL COMMENT '所属目录ID,NULL 表示未分类',
|
||||
`title` VARCHAR(200) NOT NULL COMMENT '标题',
|
||||
`content` LONGTEXT COMMENT 'Markdown正文',
|
||||
`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 '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
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='笔记表';
|
||||
|
||||
-- 插入预设分类(支出)
|
||||
|
||||
@@ -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); }
|
||||
@@ -3,188 +3,17 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>笔记管理</title>
|
||||
<style>
|
||||
: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 {
|
||||
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>
|
||||
<title>强宝小助手</title>
|
||||
<link rel="stylesheet" href="/admin/vendor/vditor/dist/index.css">
|
||||
<link rel="stylesheet" href="/admin/admin.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ==================== 登录 ==================== -->
|
||||
<div id="login-view">
|
||||
<div class="login-box">
|
||||
<h1>笔记管理</h1>
|
||||
<p class="sub">使用手机端同一个账号登录</p>
|
||||
<h1>强宝小助手</h1>
|
||||
<p class="sub">强宝管理小助手</p>
|
||||
<div class="field">
|
||||
<label>用户名</label>
|
||||
<input id="login-username" autocomplete="username" placeholder="用户名">
|
||||
@@ -197,31 +26,73 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 主界面 ==================== -->
|
||||
<!-- ==================== 主界面 ====================
|
||||
三层结构:
|
||||
顶栏 —— 系统级,只放品牌和用户操作(跨模块的东西才配放这儿)
|
||||
模块菜单 —— 左侧,以后加 Agent 等模块直接往这里塞
|
||||
模块面板 —— 当前模块自己的工具栏、侧栏和内容
|
||||
-->
|
||||
<div id="app-view" style="display:none">
|
||||
<header>
|
||||
<h1>笔记管理</h1>
|
||||
<div class="search"><input id="search" placeholder="搜索标题和正文…"></div>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand"><span class="brand-icon">🐻</span>强宝小助手</div>
|
||||
<div class="spacer"></div>
|
||||
<span class="who" id="who"></span>
|
||||
<button id="new-btn" class="primary">+ 新建</button>
|
||||
<button id="logout-btn">退出</button>
|
||||
</header>
|
||||
|
||||
<div class="layout">
|
||||
<aside class="tags">
|
||||
<h3>标签</h3>
|
||||
<div class="console">
|
||||
|
||||
<nav class="module-nav">
|
||||
<button class="module-item active" data-module="notes">
|
||||
<span class="mi-icon">📝</span>
|
||||
<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 class="module-body">
|
||||
|
||||
<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>
|
||||
<main class="content">
|
||||
<div class="breadcrumb" id="breadcrumb"></div>
|
||||
|
||||
<div id="dropzone">
|
||||
把 <b>.md</b> 文件拖到这里批量导入,或 <a href="#" id="pick-files">点击选择文件</a>
|
||||
把 <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>
|
||||
|
||||
@@ -233,418 +104,33 @@
|
||||
<input class="tags" id="ed-tags" placeholder="标签,逗号分隔">
|
||||
</div>
|
||||
<div class="editor-body">
|
||||
<textarea id="ed-content" placeholder="在这里写 Markdown…"></textarea>
|
||||
<div class="preview" id="ed-preview"></div>
|
||||
<div id="vditor"></div>
|
||||
</div>
|
||||
<div class="editor-foot">
|
||||
<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 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 id="toast"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked@12/marked.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"></script>
|
||||
<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, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
}
|
||||
|
||||
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 = '';
|
||||
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>
|
||||
<!-- Vditor:本地托管,不依赖任何外部 CDN -->
|
||||
<script src="/admin/vendor/vditor/dist/index.min.js"></script>
|
||||
<script src="/admin/admin.js"></script>
|
||||
</body>
|
||||
</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;
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
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 |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -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.
|
||||
@@ -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}
|
||||