Skip to content

Commit

Permalink
Update to pass by reference for style attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
justin-taylor committed Dec 17, 2024
1 parent 823026e commit 6627279
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 59 deletions.
53 changes: 25 additions & 28 deletions srt.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ func ReadFromSRT(i io.Reader) (o *Subtitles, err error) {
o = NewSubtitles()
var scanner = bufio.NewScanner(i)

styles := StyleAttributes{}
// Scan
var line string
var lineNum int
var s = &Item{}
var sa = &StyleAttributes{}
for scanner.Scan() {
// Fetch line
line = strings.TrimSpace(scanner.Text())
Expand All @@ -59,9 +59,8 @@ func ReadFromSRT(i io.Reader) (o *Subtitles, err error) {

// Line contains time boundaries
if strings.Contains(line, srtTimeBoundariesSeparator) {

// reset styles
styles = StyleAttributes{}
// Reset style attributes
sa = &StyleAttributes{}

// Remove last item of previous subtitle since it should be the index.
// If the last line is empty then the item is missing an index.
Expand Down Expand Up @@ -123,8 +122,7 @@ func ReadFromSRT(i io.Reader) (o *Subtitles, err error) {
o.Items = append(o.Items, s)
} else {
// Add text
var l Line
if l, styles = parseTextSrt(line, styles); len(l.Items) > 0 {
if l := parseTextSrt(line, sa); len(l.Items) > 0 {
s.Lines = append(s.Lines, l)
}
}
Expand All @@ -133,12 +131,11 @@ func ReadFromSRT(i io.Reader) (o *Subtitles, err error) {
}

// parseTextSrt parses the input line to fill the Line
func parseTextSrt(i string, styles StyleAttributes) (Line, StyleAttributes) {
func parseTextSrt(i string, sa *StyleAttributes) (o Line) {
// special handling needed for empty line
o := Line{}
if i == "" {
if strings.TrimSpace(i) == "" {
o.Items = []LineItem{{Text: ""}}
return o, styles
return
}

// Create tokenizer
Expand All @@ -164,51 +161,51 @@ func parseTextSrt(i string, styles StyleAttributes) (Line, StyleAttributes) {
// Parse italic/bold/underline
switch token.Data {
case "b":
styles.SRTBold = false
sa.SRTBold = false
case "i":
styles.SRTItalics = false
sa.SRTItalics = false
case "u":
styles.SRTUnderline = false
sa.SRTUnderline = false
case "font":
styles.SRTColor = nil
sa.SRTColor = nil
}
case html.StartTagToken:
// Parse italic/bold/underline
switch token.Data {
case "b":
styles.SRTBold = true
sa.SRTBold = true
case "i":
styles.SRTItalics = true
sa.SRTItalics = true
case "u":
styles.SRTUnderline = true
sa.SRTUnderline = true
case "font":
if c := htmlTokenAttribute(&token, "color"); c != nil {
styles.SRTColor = c
sa.SRTColor = c
}
}
case html.TextToken:
if s := strings.TrimSpace(raw); s != "" {
// Get style attribute
var sa *StyleAttributes
if styles.SRTBold || styles.SRTColor != nil || styles.SRTItalics || styles.SRTUnderline {
sa = &StyleAttributes{
SRTBold: styles.SRTBold,
SRTColor: styles.SRTColor,
SRTItalics: styles.SRTItalics,
SRTUnderline: styles.SRTUnderline,
var styleAttributes *StyleAttributes
if sa.SRTBold || sa.SRTColor != nil || sa.SRTItalics || sa.SRTUnderline {
styleAttributes = &StyleAttributes{
SRTBold: sa.SRTBold,
SRTColor: sa.SRTColor,
SRTItalics: sa.SRTItalics,
SRTUnderline: sa.SRTUnderline,
}
sa.propagateSRTAttributes()
styleAttributes.propagateSRTAttributes()
}

// Append item
o.Items = append(o.Items, LineItem{
InlineStyle: sa,
InlineStyle: styleAttributes,
Text: unescapeHTML(s),
})
}
}
}
return o, styles
return
}

// formatDurationSRT formats an .srt duration
Expand Down
48 changes: 23 additions & 25 deletions webvtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
var scanner = bufio.NewScanner(i)
var line string
var lineNum int
webVTTTagStack := make([]WebVTTTag, 0, 16)

// Skip the header
for scanner.Scan() {
Expand All @@ -142,7 +141,7 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
var blockName string
var comments []string
var index int
var webVTTStyles *StyleAttributes
var sa = &StyleAttributes{}

for scanner.Scan() {
// Fetch line
Expand All @@ -163,13 +162,14 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
// Reset block name, if we are not in the middle of CSS.
// If we are in STYLE block and the CSS is empty or we meet the right brace at the end of last line,
// then we are not in CSS and can switch to parse next WebVTT block.
if blockName != webvttBlockNameStyle || webVTTStyles == nil ||
len(webVTTStyles.WebVTTStyles) == 0 ||
strings.HasSuffix(webVTTStyles.WebVTTStyles[len(webVTTStyles.WebVTTStyles)-1], "}") {
if blockName != webvttBlockNameStyle || sa == nil ||
len(sa.WebVTTStyles) == 0 ||
strings.HasSuffix(sa.WebVTTStyles[len(sa.WebVTTStyles)-1], "}") {
blockName = ""
}
// Reset tag stack
webVTTTagStack = make([]WebVTTTag, 0, 16)

// Reset WebVTTTags
sa.WebVTTTags = []WebVTTTag{}

// Region
case strings.HasPrefix(line, "Region: "):
Expand Down Expand Up @@ -211,9 +211,9 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
blockName = webvttBlockNameStyle

if _, ok := o.Styles[webvttDefaultStyleID]; !ok {
webVTTStyles = &StyleAttributes{}
sa = &StyleAttributes{}
o.Styles[webvttDefaultStyleID] = &Style{
InlineStyle: webVTTStyles,
InlineStyle: sa,
ID: webvttDefaultStyleID,
}
}
Expand Down Expand Up @@ -318,12 +318,11 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
case webvttBlockNameComment:
comments = append(comments, line)
case webvttBlockNameStyle:
webVTTStyles.WebVTTStyles = append(webVTTStyles.WebVTTStyles, line)
sa.WebVTTStyles = append(sa.WebVTTStyles, line)
case webvttBlockNameText:
// Parse line
if l, stack := parseTextWebVTT(line, webVTTTagStack); len(l.Items) > 0 {
if l := parseTextWebVTT(line, sa); len(l.Items) > 0 {
item.Lines = append(item.Lines, l)
webVTTTagStack = stack
}
default:
// This is the ID
Expand All @@ -335,10 +334,9 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
}

// parseTextWebVTT parses the input line to fill the Line
func parseTextWebVTT(i string, webVTTTagStack []WebVTTTag) (Line, []WebVTTTag) {
func parseTextWebVTT(i string, sa *StyleAttributes) (o Line) {
// Create tokenizer
tr := html.NewTokenizer(strings.NewReader(i))
o := Line{}

// Loop
for {
Expand All @@ -352,8 +350,8 @@ func parseTextWebVTT(i string, webVTTTagStack []WebVTTTag) (Line, []WebVTTTag) {
switch t {
case html.EndTagToken:
// Pop the top of stack if we meet end tag
if len(webVTTTagStack) > 0 {
webVTTTagStack = webVTTTagStack[:len(webVTTTagStack)-1]
if len(sa.WebVTTTags) > 0 {
sa.WebVTTTags = sa.WebVTTTags[:len(sa.WebVTTTags)-1]
}
case html.StartTagToken:
if matches := webVTTRegexpTag.FindStringSubmatch(string(tr.Raw())); len(matches) > 4 {
Expand Down Expand Up @@ -381,7 +379,7 @@ func parseTextWebVTT(i string, webVTTTagStack []WebVTTTag) (Line, []WebVTTTag) {
}

// Push the tag to stack
webVTTTagStack = append(webVTTTagStack, WebVTTTag{
sa.WebVTTTags = append(sa.WebVTTTags, WebVTTTag{
Name: tagName,
Classes: classes,
Annotation: annotation,
Expand All @@ -390,21 +388,21 @@ func parseTextWebVTT(i string, webVTTTagStack []WebVTTTag) (Line, []WebVTTTag) {

case html.TextToken:
// Get style attribute
var sa *StyleAttributes
if len(webVTTTagStack) > 0 {
tags := make([]WebVTTTag, len(webVTTTagStack))
copy(tags, webVTTTagStack)
sa = &StyleAttributes{
var styleAttributes *StyleAttributes
if len(sa.WebVTTTags) > 0 {
tags := make([]WebVTTTag, len(sa.WebVTTTags))
copy(tags, sa.WebVTTTags)
styleAttributes = &StyleAttributes{
WebVTTTags: tags,
}
sa.propagateWebVTTAttributes()
styleAttributes.propagateWebVTTAttributes()
}

// Append items
o.Items = append(o.Items, parseTextWebVTTTextToken(sa, string(tr.Raw()))...)
o.Items = append(o.Items, parseTextWebVTTTextToken(styleAttributes, string(tr.Raw()))...)
}
}
return o, webVTTTagStack
return
}

func parseTextWebVTTTextToken(sa *StyleAttributes, line string) (ret []LineItem) {
Expand Down
12 changes: 6 additions & 6 deletions webvtt_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestParseTextWebVTT(t *testing.T) {
t.Run("When both voice tags are available", func(t *testing.T) {
testData := `<v Bob>Correct tag</v>`

s, _ := parseTextWebVTT(testData, make([]WebVTTTag, 0, 16))
s := parseTextWebVTT(testData, &StyleAttributes{})
assert.Equal(t, "Bob", s.VoiceName)
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "Correct tag", s.Items[0].Text)
Expand All @@ -22,7 +22,7 @@ func TestParseTextWebVTT(t *testing.T) {
t.Run("When there is no end tag", func(t *testing.T) {
testData := `<v Bob> Text without end tag`

s, _ := parseTextWebVTT(testData, make([]WebVTTTag, 0, 16))
s := parseTextWebVTT(testData, &StyleAttributes{})
assert.Equal(t, "Bob", s.VoiceName)
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "Text without end tag", s.Items[0].Text)
Expand All @@ -31,7 +31,7 @@ func TestParseTextWebVTT(t *testing.T) {
t.Run("When the end tag is correct", func(t *testing.T) {
testData := `<v Bob>Incorrect end tag</vi>`

s, _ := parseTextWebVTT(testData, make([]WebVTTTag, 0, 16))
s := parseTextWebVTT(testData, &StyleAttributes{})
assert.Equal(t, "Bob", s.VoiceName)
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "Incorrect end tag", s.Items[0].Text)
Expand All @@ -40,7 +40,7 @@ func TestParseTextWebVTT(t *testing.T) {
t.Run("When inline timestamps are included", func(t *testing.T) {
testData := `<00:01:01.000>With inline <00:01:02.000>timestamps`

s, _ := parseTextWebVTT(testData, make([]WebVTTTag, 0, 16))
s := parseTextWebVTT(testData, &StyleAttributes{})
assert.Equal(t, 2, len(s.Items))
assert.Equal(t, "With inline", s.Items[0].Text)
assert.Equal(t, time.Minute+time.Second, s.Items[0].StartAt)
Expand All @@ -51,7 +51,7 @@ func TestParseTextWebVTT(t *testing.T) {
t.Run("When inline timestamps together", func(t *testing.T) {
testData := `<00:01:01.000><00:01:02.000>With timestamp tags together`

s, _ := parseTextWebVTT(testData, make([]WebVTTTag, 0, 16))
s := parseTextWebVTT(testData, &StyleAttributes{})
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "With timestamp tags together", s.Items[0].Text)
assert.Equal(t, time.Minute+2*time.Second, s.Items[0].StartAt)
Expand All @@ -60,7 +60,7 @@ func TestParseTextWebVTT(t *testing.T) {
t.Run("When inline timestamps is at end", func(t *testing.T) {
testData := `With end timestamp<00:01:02.000>`

s, _ := parseTextWebVTT(testData, make([]WebVTTTag, 0, 16))
s := parseTextWebVTT(testData, &StyleAttributes{})
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "With end timestamp", s.Items[0].Text)
assert.Equal(t, time.Duration(0), s.Items[0].StartAt)
Expand Down

0 comments on commit 6627279

Please sign in to comment.