Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme Injection #1243

Open
prescience-data opened this issue Apr 26, 2023 · 0 comments
Open

Theme Injection #1243

prescience-data opened this issue Apr 26, 2023 · 0 comments

Comments

@prescience-data
Copy link

prescience-data commented Apr 26, 2023

Just wondering if you'd be interested a PR that touches this component to inject custom theme data, which would allow referencing colours by relative accent1 tags rather than absolute hex codes?

export function makeXmlTheme (pres: IPresentationProps): string {

I prefer to get input before unilaterally trying to make any design decisions in the PR, so just opening this ticket as a discussion point first.

This pseudocode is roughly what I had in mind:

import PptxGenJS from "pptxgenjs"

import HexColor = PptxGenJS.HexColor
import ThemeColor = PptxGenJS.ThemeColor

/** Update existing theme props. */
export interface ThemeProps {
  name?: string
  colors: Record<ThemeColor, HexColor>
  headFontFace?: string
  bodyFontFace?: string
}

/** Update existing presentation props. */
export interface IPresentationProps {
  theme: ThemeProps
}

/** Inject theme into presentation. */
export function makeXmlTheme({
  theme: {
    name = "Office",
    colors, // TODO: Resolve default colors.
    headFontFace = "Calibri Light",
    bodyFontFace = "Calibri"
  }
}: IPresentationProps): string {
  return /* language=XML */ `
      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">
          <a:themeElements>
              <a:clrScheme name="${name}">
                  <a:dk1>
                      <a:sysClr val="windowText" lastClr="${colors.tx1.replace(/^#/, ``)}"/>
                  </a:dk1>
                  <a:lt1>
                      <a:sysClr val="window" lastClr="${colors.bg1.replace(/^#/, ``)}"/>
                  </a:lt1>
                  <a:dk2>
                      <a:srgbClr val="${colors.tx2.replace(/^#/, ``)}"/>
                  </a:dk2>
                  <a:lt2>
                      <a:srgbClr val="${colors.bg2.replace(/^#/, ``)}"/>
                  </a:lt2>
                  <a:accent1>
                      <a:srgbClr val="${colors.accent1.replace(/^#/, ``)}"/>
                  </a:accent1>
                  <a:accent2>
                      <a:srgbClr val="${colors.accent2.replace(/^#/, ``)}"/>
                  </a:accent2>
                  <a:accent3>
                      <a:srgbClr val="${colors.accent3.replace(/^#/, ``)}"/>
                  </a:accent3>
                  <a:accent4>
                      <a:srgbClr val="${colors.accent4.replace(/^#/, ``)}"/>
                  </a:accent4>
                  <a:accent5>
                      <a:srgbClr val="${colors.accent5.replace(/^#/, ``)}"/>
                  </a:accent5>
                  <a:accent6>
                      <a:srgbClr val="${colors.accent6.replace(/^#/, ``)}"/>
                  </a:accent6>
                  <a:hlink>
                      <a:srgbClr val="${colors.accent1.replace(/^#/, ``)}"/>
                  </a:hlink>
                  <a:folHlink>
                      <a:srgbClr val="${colors.accent1.replace(/^#/, ``)}"/>
                  </a:folHlink>
              </a:clrScheme>
              <a:fontScheme name="${name}">
                  <a:majorFont>
                      <a:latin typeface="${headFontFace}"/>
                      <a:ea typeface=""/>
                      <a:cs typeface=""/>
                  </a:majorFont>
                  <a:minorFont>
                      <a:latin typeface="${bodyFontFace}"/>
                      <a:ea typeface=""/>
                      <a:cs typeface=""/>
                  </a:minorFont>
              </a:fontScheme>
              /** ... rest of theme **/
      </a:theme>
  `
    .trim()
    .replace(/\n+/g, ` `)
    .replace(/>\s+</g, `><`)
}

}

FWIW I have this POC working with the following custom implementation:

 async #writeWithTheme(filename: string): Promise<void> {
    const data = await this.pptx().write({
      outputType: "nodebuffer",
      compression: false
    })

    logger.debug(`Adding office theme to "${filename}".`)
    const zip = new JSZip()

    await zip.loadAsync(data)

    zip.file("ppt/theme/theme1.xml", makeXmlTheme("Office", this.theme))

    logger.debug(`Generating zip content.`)
    const output = await zip.generateAsync({
      type: "nodebuffer",
      compression: "DEFLATE"
    })

    logger.debug(`Writing presentation to "${filename}".`)
    await writeFile(filename, output)
  }

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant