115 lines
5.4 KiB
Go
115 lines
5.4 KiB
Go
package richtext
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const userParagraphStylesPath = "/.ultidrive/docs-user-paragraph-styles.json"
|
|
|
|
type UltiDocParagraphStyleDefinition struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Scope string `json:"scope"`
|
|
BasedOn string `json:"basedOn,omitempty"`
|
|
BlockType string `json:"blockType"`
|
|
Level *int `json:"level,omitempty"`
|
|
FontFamily string `json:"fontFamily,omitempty"`
|
|
FontSizePx float64 `json:"fontSizePx,omitempty"`
|
|
Bold *bool `json:"bold,omitempty"`
|
|
Italic *bool `json:"italic,omitempty"`
|
|
Underline *bool `json:"underline,omitempty"`
|
|
Color string `json:"color,omitempty"`
|
|
TextAlign string `json:"textAlign,omitempty"`
|
|
LineHeight float64 `json:"lineHeight,omitempty"`
|
|
SpaceBeforePt float64 `json:"spaceBeforePt,omitempty"`
|
|
SpaceAfterPt float64 `json:"spaceAfterPt,omitempty"`
|
|
}
|
|
|
|
type UltiDocParagraphStyles struct {
|
|
Definitions map[string]UltiDocParagraphStyleDefinition `json:"definitions"`
|
|
}
|
|
|
|
type DocsFontDefinition struct {
|
|
Name string `json:"name"`
|
|
Stack string `json:"stack"`
|
|
Source string `json:"source,omitempty"`
|
|
URL string `json:"url,omitempty"`
|
|
}
|
|
|
|
var defaultDocsFonts = []DocsFontDefinition{
|
|
{Name: "Arial", Stack: "Arial, Helvetica, sans-serif", Source: "system"},
|
|
{Name: "Calibri", Stack: "Calibri, Candara, Segoe, sans-serif", Source: "system"},
|
|
{Name: "Comic Sans MS", Stack: `"Comic Sans MS", cursive, sans-serif`, Source: "system"},
|
|
{Name: "Courier New", Stack: `"Courier New", Courier, monospace`, Source: "system"},
|
|
{Name: "Georgia", Stack: "Georgia, serif", Source: "system"},
|
|
{Name: "Times New Roman", Stack: `"Times New Roman", Times, serif`, Source: "system"},
|
|
{Name: "Trebuchet MS", Stack: `"Trebuchet MS", Helvetica, sans-serif`, Source: "system"},
|
|
{Name: "Verdana", Stack: "Verdana, Geneva, sans-serif", Source: "system"},
|
|
}
|
|
|
|
func defaultUltiDocParagraphStyles() UltiDocParagraphStyles {
|
|
level := func(n int) *int { v := n; return &v }
|
|
bold := func(v bool) *bool { return &v }
|
|
italic := func(v bool) *bool { return &v }
|
|
return UltiDocParagraphStyles{
|
|
Definitions: map[string]UltiDocParagraphStyleDefinition{
|
|
"normal": {ID: "normal", Name: "Normal", Scope: "document", BlockType: "paragraph", FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 11, LineHeight: 1.15},
|
|
"title": {ID: "title", Name: "Titre", Scope: "document", BlockType: "paragraph", FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 26, LineHeight: 1.15},
|
|
"subtitle": {ID: "subtitle", Name: "Sous-titre", Scope: "document", BlockType: "paragraph", FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 15, Color: "#666666", LineHeight: 1.15},
|
|
"heading1": {ID: "heading1", Name: "Titre 1", Scope: "document", BlockType: "heading", Level: level(1), FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 20, LineHeight: 1.15},
|
|
"heading2": {ID: "heading2", Name: "Titre 2", Scope: "document", BlockType: "heading", Level: level(2), FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 16, LineHeight: 1.15},
|
|
"heading3": {ID: "heading3", Name: "Titre 3", Scope: "document", BlockType: "heading", Level: level(3), FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 14, LineHeight: 1.15},
|
|
"heading4": {ID: "heading4", Name: "Titre 4", Scope: "document", BlockType: "heading", Level: level(4), FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 12, Bold: bold(true), LineHeight: 1.15},
|
|
"heading5": {ID: "heading5", Name: "Titre 5", Scope: "document", BlockType: "heading", Level: level(5), FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 11, Bold: bold(true), LineHeight: 1.15},
|
|
"heading6": {ID: "heading6", Name: "Titre 6", Scope: "document", BlockType: "heading", Level: level(6), FontFamily: "Arial, Helvetica, sans-serif", FontSizePx: 11, Italic: italic(true), LineHeight: 1.15},
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *Service) ListFonts(_ context.Context) []DocsFontDefinition {
|
|
out := make([]DocsFontDefinition, len(defaultDocsFonts))
|
|
copy(out, defaultDocsFonts)
|
|
return out
|
|
}
|
|
|
|
func (s *Service) LoadUserParagraphStyles(ctx context.Context, ncUser string) (UltiDocParagraphStyles, error) {
|
|
body, err := s.LoadDocument(ctx, ncUser, userParagraphStylesPath)
|
|
if err != nil || len(body) == 0 {
|
|
return UltiDocParagraphStyles{Definitions: map[string]UltiDocParagraphStyleDefinition{}}, nil
|
|
}
|
|
var styles UltiDocParagraphStyles
|
|
if err := json.Unmarshal(body, &styles); err != nil {
|
|
return UltiDocParagraphStyles{}, fmt.Errorf("parse user paragraph styles: %w", err)
|
|
}
|
|
if styles.Definitions == nil {
|
|
styles.Definitions = map[string]UltiDocParagraphStyleDefinition{}
|
|
}
|
|
return styles, nil
|
|
}
|
|
|
|
func (s *Service) SaveUserParagraphStyles(ctx context.Context, ncUser string, styles UltiDocParagraphStyles) error {
|
|
if styles.Definitions == nil {
|
|
styles.Definitions = map[string]UltiDocParagraphStyleDefinition{}
|
|
}
|
|
payload, err := json.MarshalIndent(styles, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return s.nc.Upload(ctx, ncUser, userParagraphStylesPath, strings.NewReader(string(payload)), "application/json")
|
|
}
|
|
|
|
func (s *Service) loadParagraphStylesFromSidecar(ctx context.Context, ncUser, canonical string) (json.RawMessage, error) {
|
|
raw, err := s.LoadDocument(ctx, ncUser, canonical)
|
|
if err != nil || len(raw) == 0 {
|
|
return nil, err
|
|
}
|
|
doc, err := ParseUltiDoc(raw)
|
|
if err != nil || doc.ParagraphStyles == nil {
|
|
return nil, err
|
|
}
|
|
return json.Marshal(doc.ParagraphStyles)
|
|
}
|