Markdown with supress <p>
This commit is contained in:
parent
b0c7b6a690
commit
2ba61f10ff
@ -2,10 +2,12 @@ package aboutme
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"path"
|
||||
"personalwebsite/apps/appCtx"
|
||||
"personalwebsite/errormessage"
|
||||
"personalwebsite/libs"
|
||||
"personalwebsite/webfilesystem"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -15,6 +17,7 @@ import (
|
||||
type AboutMeApp struct {
|
||||
fs *webfilesystem.WebFileSystem
|
||||
appID string
|
||||
mLib libs.MarkdownLib
|
||||
}
|
||||
|
||||
func NewAboutMeApp(webFs *webfilesystem.WebFileSystem) *AboutMeApp {
|
||||
@ -54,12 +57,35 @@ func (p *AboutMeApp) PublicRoutes(route *gin.RouterGroup) {
|
||||
|
||||
func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
||||
p.PublicRoutes(router)
|
||||
router.GET("writeMock", func(ctx *gin.Context) {
|
||||
err := p.WriteMock()
|
||||
if err != nil {
|
||||
ctx.Status(http.StatusInternalServerError)
|
||||
}
|
||||
ctx.Status(http.StatusOK)
|
||||
// router.GET("writeMock", func(ctx *gin.Context) {
|
||||
// err := p.WriteMock()
|
||||
// if err != nil {
|
||||
// ctx.Status(http.StatusInternalServerError)
|
||||
// }
|
||||
// ctx.Status(http.StatusOK)
|
||||
// })
|
||||
|
||||
router.GET("getMock", func(ctx *gin.Context) {
|
||||
ctx.JSON(http.StatusOK, PropertiesFileData{
|
||||
Header: HeaderIsland{},
|
||||
Islands: []Island{
|
||||
{
|
||||
Header: "qq",
|
||||
Properties: []IslandProperty{
|
||||
{
|
||||
Key: "22",
|
||||
KeyComments: []string{
|
||||
"45",
|
||||
"12",
|
||||
},
|
||||
Values: []string{
|
||||
"aaaa",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
router.GET("read", func(ctx *gin.Context) {
|
||||
@ -93,7 +119,9 @@ func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
||||
propsData := PropertiesFileData{}
|
||||
err := ctx.BindJSON(&propsData)
|
||||
if err != nil {
|
||||
ctx.Status(http.StatusBadRequest)
|
||||
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@ -113,72 +141,72 @@ func (p *AboutMeApp) GetAppID() string {
|
||||
return p.appID
|
||||
}
|
||||
|
||||
func (p *AboutMeApp) WriteMock() error {
|
||||
fileHeader := webfilesystem.FileHeader{
|
||||
MongoId: primitive.NewObjectID(),
|
||||
Name: "aboutme.props",
|
||||
Type: "personal-properties",
|
||||
Icon: "",
|
||||
}
|
||||
fileData := PropertiesFileData{
|
||||
Header: HeaderIsland{
|
||||
Name: "Test Name",
|
||||
IconPath: "test icon path",
|
||||
Info1: "Info1",
|
||||
Info2: "Info2",
|
||||
},
|
||||
Props: []PropIsland{
|
||||
{
|
||||
Header: "Test Prop Header",
|
||||
Props: []PropElement{
|
||||
{
|
||||
Key: "Test key",
|
||||
KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
||||
Values: []Value{
|
||||
{
|
||||
Blocks: []Block{
|
||||
{
|
||||
Type: "string",
|
||||
Data: []string{"aappo"},
|
||||
},
|
||||
{
|
||||
Type: "link",
|
||||
Data: []string{"https://ya.ru", "Azazaza"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "Test Prop Header 2",
|
||||
Props: []PropElement{
|
||||
{
|
||||
Key: "Test key",
|
||||
KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
||||
Values: []Value{
|
||||
{
|
||||
Blocks: []Block{
|
||||
{
|
||||
Type: "string",
|
||||
Data: []string{"aappo"},
|
||||
},
|
||||
{
|
||||
Type: "link",
|
||||
Data: []string{"https://ya.ru", "Azazaza"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
||||
return err
|
||||
}
|
||||
// func (p *AboutMeApp) WriteMock() error {
|
||||
// fileHeader := webfilesystem.FileHeader{
|
||||
// MongoId: primitive.NewObjectID(),
|
||||
// Name: "aboutme.props",
|
||||
// Type: "personal-properties",
|
||||
// Icon: "",
|
||||
// }
|
||||
// fileData := PropertiesFileData{
|
||||
// Header: HeaderIsland{
|
||||
// Name: "Test Name",
|
||||
// IconPath: "test icon path",
|
||||
// Info1: "Info1",
|
||||
// Info2: "Info2",
|
||||
// },
|
||||
// Props: []PropIsland{
|
||||
// {
|
||||
// Header: "Test Prop Header",
|
||||
// Props: []PropElement{
|
||||
// {
|
||||
// Key: "Test key",
|
||||
// KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
||||
// Values: []Value{
|
||||
// {
|
||||
// Blocks: []ValueBlock{
|
||||
// {
|
||||
// Type: "string",
|
||||
// Data: []string{"aappo"},
|
||||
// },
|
||||
// {
|
||||
// Type: "link",
|
||||
// Data: []string{"https://ya.ru", "Azazaza"},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Header: "Test Prop Header 2",
|
||||
// Props: []PropElement{
|
||||
// {
|
||||
// Key: "Test key",
|
||||
// KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
||||
// Values: []Value{
|
||||
// {
|
||||
// Blocks: []ValueBlock{
|
||||
// {
|
||||
// Type: "string",
|
||||
// Data: []string{"aappo"},
|
||||
// },
|
||||
// {
|
||||
// Type: "link",
|
||||
// Data: []string{"https://ya.ru", "Azazaza"},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// _, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (p *AboutMeApp) Read(filePath string) (*PropertiesFileData, error) {
|
||||
propData := PropertiesFileData{}
|
||||
@ -215,47 +243,84 @@ func (p *AboutMeApp) Edit(filePath string, blogData PropertiesFileData) error {
|
||||
}
|
||||
|
||||
func (p *AboutMeApp) Render(appCtx appCtx.AppContext, filePath string) (gin.H, error) {
|
||||
propsData := PropertiesFileData{}
|
||||
//Read file from WebFS
|
||||
propsData := &PropertiesFileData{}
|
||||
filePath = p.fs.RelativeToAbsolute(appCtx, filePath)
|
||||
_, err := p.fs.Read(filePath, &propsData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Render Markdown strings
|
||||
renderedIslands := []RenderedIsland{}
|
||||
for _, island := range propsData.Islands {
|
||||
newRenderedIsland := RenderedIsland{
|
||||
Header: island.Header,
|
||||
Properties: []RenderedIslandProperty{},
|
||||
}
|
||||
for _, property := range island.Properties {
|
||||
newRenderedIslandProperty := RenderedIslandProperty{
|
||||
Key: property.Key,
|
||||
KeyComments: property.KeyComments,
|
||||
Values: []template.HTML{},
|
||||
}
|
||||
for _, value := range property.Values {
|
||||
renderedValue := p.mLib.Render([]byte(value), true)
|
||||
newRenderedIslandProperty.Values = append(newRenderedIslandProperty.Values, renderedValue)
|
||||
}
|
||||
newRenderedIsland.Properties = append(newRenderedIsland.Properties, newRenderedIslandProperty)
|
||||
}
|
||||
renderedIslands = append(renderedIslands, newRenderedIsland)
|
||||
}
|
||||
|
||||
//Make icon path absolute
|
||||
propsData.Header.IconPath = p.fs.RelativeToAbsolute(appCtx, propsData.Header.IconPath)
|
||||
|
||||
return gin.H{
|
||||
"headerProps": propsData.Header,
|
||||
"allprops": propsData.Props,
|
||||
"HeaderProps": propsData.Header,
|
||||
"Islands": renderedIslands,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type PropertiesFileData struct {
|
||||
Header HeaderIsland `bson:"header"`
|
||||
Islands []Island `bson:"islands"` //TODO rename
|
||||
}
|
||||
|
||||
type HeaderIsland struct {
|
||||
Name string `bson:"name"`
|
||||
IconPath string `bson:"iconpath"`
|
||||
Info1 string `bson:"info1"`
|
||||
Info2 string `bson:"info2"`
|
||||
Value1 string `bson:"value1"` //TODO Rename to value
|
||||
Value2 string `bson:"value2"`
|
||||
}
|
||||
|
||||
type PropElement struct {
|
||||
type Island struct {
|
||||
Header string `bson:"header"`
|
||||
Properties []IslandProperty `bson:"properties"`
|
||||
}
|
||||
|
||||
type IslandProperty struct {
|
||||
Key string `bson:"key"`
|
||||
KeyComments []string `bson:"keycomment"`
|
||||
Values []string `bson:"values"`
|
||||
}
|
||||
|
||||
type RenderedIsland struct {
|
||||
Header string
|
||||
Properties []RenderedIslandProperty
|
||||
}
|
||||
|
||||
type RenderedIslandProperty struct {
|
||||
Key string
|
||||
KeyComments []string
|
||||
Values []Value
|
||||
Values []template.HTML
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
Blocks []Block
|
||||
}
|
||||
// type Value struct {
|
||||
// Blocks []ValueBlock
|
||||
// }
|
||||
|
||||
type Block struct {
|
||||
Type string
|
||||
Data []string
|
||||
}
|
||||
|
||||
type PropIsland struct {
|
||||
Header string
|
||||
Props []PropElement
|
||||
}
|
||||
|
||||
type PropertiesFileData struct {
|
||||
Header HeaderIsland `bson:"header"`
|
||||
Props []PropIsland `bson:"props"`
|
||||
}
|
||||
// type ValueBlock struct {
|
||||
// Type string
|
||||
// Data string
|
||||
// }
|
||||
|
@ -45,7 +45,7 @@ func (b *BlogViewerApplication) PrivateRoutes(route *gin.RouterGroup) {
|
||||
for _, block := range blogData.Blocks {
|
||||
for _, str := range block.Data {
|
||||
test := []byte(str)
|
||||
mLib.Render(test)
|
||||
mLib.Render(test, true)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -239,7 +239,7 @@ func (b *BlogViewerApplication) Render(filePath string, appCtx appCtx.AppContext
|
||||
// }
|
||||
case "markdown":
|
||||
for _, data := range block.Data {
|
||||
renderedMD := b.mLib.Render([]byte(data))
|
||||
renderedMD := b.mLib.Render([]byte(data), true)
|
||||
newBlock.Data = append(newBlock.Data, renderedMD)
|
||||
}
|
||||
newData = append(newData, newBlock)
|
||||
|
@ -2,6 +2,7 @@ package libs
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"strings"
|
||||
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
"github.com/russross/blackfriday/v2"
|
||||
@ -10,8 +11,12 @@ import (
|
||||
type MarkdownLib struct {
|
||||
}
|
||||
|
||||
func (ml *MarkdownLib) Render(s []byte) template.HTML {
|
||||
output := blackfriday.Run(s)
|
||||
func (ml *MarkdownLib) Render(md []byte, supressParagraph bool) template.HTML {
|
||||
output := blackfriday.Run(md)
|
||||
if supressParagraph {
|
||||
output = []byte(strings.ReplaceAll(string(output), "<p>", ""))
|
||||
output = []byte(strings.ReplaceAll(string(output), "</p>", ""))
|
||||
}
|
||||
_ = output
|
||||
html := bluemonday.UGCPolicy().SanitizeBytes(output)
|
||||
// println(string(html))
|
||||
|
@ -42,17 +42,17 @@ func PrivateRoutes(port string, webfs *webfilesystem.WebFileSystem, webde *wde.W
|
||||
Args: []string{"/home/user/Blogs/blog1.blog"},
|
||||
}
|
||||
|
||||
// aboutMe := AppString{
|
||||
// AppPath: "/Applications/AboutMe.app",
|
||||
// Args: []string{},
|
||||
// }
|
||||
aboutMe := AppString{
|
||||
AppPath: "/Applications/AboutMe.app",
|
||||
Args: []string{},
|
||||
}
|
||||
|
||||
// appString2 := AppString{
|
||||
// AppPath: "/Applications/Finder.app",
|
||||
// Args: []string{"/home/user/", "--desktop", "desktop-layer"},
|
||||
// }
|
||||
|
||||
autostart := []AppString{appString}
|
||||
autostart := []AppString{appString, aboutMe}
|
||||
ctx.HTML(http.StatusOK, "index.tmpl", gin.H{
|
||||
"autostart": autostart,
|
||||
})
|
||||
|
@ -12,44 +12,31 @@
|
||||
<div class="PropsView">
|
||||
<div class="PropertiesList">
|
||||
<div class="ShortBio">
|
||||
<img class="Image" src="/system/libs/img/get?path={{ .headerProps.IconPath }}" alt="My Photo">
|
||||
<img class="Image" src="/system/libs/img/get?path={{ .HeaderProps.IconPath }}" alt="My Photo">
|
||||
<div class="Text">
|
||||
<div class="Name">{{ .headerProps.Name }}</div>
|
||||
<div>{{ .headerProps.Info1 }}</div>
|
||||
<div>{{ .headerProps.Info2 }}</div>
|
||||
<div class="Name">{{ .HeaderProps.Name }}</div>
|
||||
<div>{{ .HeaderProps.Value1 }}</div>
|
||||
<div>{{ .HeaderProps.Value2 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ range $propIsland := .allprops }}
|
||||
<!-- FIXME -->
|
||||
<div class="Island">
|
||||
<div class="Title">
|
||||
{{$propIsland.Header}}:
|
||||
</div>
|
||||
{{ range $island := .Islands }}
|
||||
<!-- FIXME -->
|
||||
|
||||
<div class="Island">
|
||||
<div class="Title"> {{$island.Header}}:</div>
|
||||
<div class="Content">
|
||||
{{range $prop := $propIsland.Props}}
|
||||
|
||||
{{range $property := $island.Properties}}
|
||||
<div class="Row">
|
||||
<div class="Key">
|
||||
{{$prop.Key}}:
|
||||
{{ range $keyComment := $prop.KeyComments }}
|
||||
<div class="KeyComment">
|
||||
{{ $keyComment }}
|
||||
</div>
|
||||
{{$property.Key}}:
|
||||
{{ range $keyComment := $property.KeyComments }}
|
||||
<div class="KeyComment">{{ $keyComment }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="Values">
|
||||
{{ range $value := $prop.Values }}
|
||||
<div class="Value">
|
||||
{{ range $block := $value.Blocks }}
|
||||
{{ if eq $block.Type "link"}}
|
||||
<a href="{{ index $block.Data 0}}">{{ index $block.Data 1}}</a>
|
||||
{{ end }}
|
||||
{{ if eq $block.Type "string"}}
|
||||
{{ range $string := $block.Data}}
|
||||
{{ $string }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ range $value := $property.Values }}
|
||||
<div class="Value">{{ $value }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user