Untitled

 avatar
unknown
plain_text
2 months ago
26 kB
9
Indexable
const {
  Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
  HeadingLevel, AlignmentType, BorderStyle, WidthType, ShadingType,
  LevelFormat, PageBreak
} = require('docx');
const fs = require('fs');

const BLUE = "1F4E79";
const LIGHT_BLUE = "D6E4F0";
const GOLD = "7B5A00";
const LIGHT_GOLD = "FFF3CD";
const GREEN = "1A4731";
const LIGHT_GREEN = "D4EDDA";
const DARK = "212121";
const MID_GREY = "555555";
const RED = "8B0000";
const LIGHT_RED = "FDECEA";
const BORDER_GREY = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
const BORDERS = { top: BORDER_GREY, bottom: BORDER_GREY, left: BORDER_GREY, right: BORDER_GREY };
const NO_BORDER = { style: BorderStyle.NONE, size: 0, color: "FFFFFF" };
const NO_BORDERS = { top: NO_BORDER, bottom: NO_BORDER, left: NO_BORDER, right: NO_BORDER };

function heading1(text, color = BLUE) {
  return new Paragraph({
    heading: HeadingLevel.HEADING_1,
    spacing: { before: 320, after: 120 },
    border: { bottom: { style: BorderStyle.SINGLE, size: 8, color, space: 4 } },
    children: [new TextRun({ text, bold: true, size: 36, color, font: "Arial" })]
  });
}

function heading2(text) {
  return new Paragraph({
    heading: HeadingLevel.HEADING_2,
    spacing: { before: 240, after: 80 },
    children: [new TextRun({ text, bold: true, size: 28, color: DARK, font: "Arial" })]
  });
}

function heading3(text, color = MID_GREY) {
  return new Paragraph({
    spacing: { before: 160, after: 60 },
    children: [new TextRun({ text, bold: true, size: 24, color, font: "Arial", italics: true })]
  });
}

function bullet(text) {
  return new Paragraph({
    numbering: { reference: "bullets", level: 0 },
    spacing: { before: 40, after: 40 },
    children: [new TextRun({ text, font: "Arial", size: 22 })]
  });
}

function colourBox(children, fillColor = LIGHT_BLUE) {
  return new Table({
    width: { size: 9360, type: WidthType.DXA },
    columnWidths: [9360],
    rows: [new TableRow({
      children: [new TableCell({
        borders: NO_BORDERS,
        width: { size: 9360, type: WidthType.DXA },
        shading: { fill: fillColor, type: ShadingType.CLEAR },
        margins: { top: 160, bottom: 160, left: 240, right: 240 },
        children
      })]
    })]
  });
}

function quoteBox(quote, analysis, fillColor, labelColor) {
  return new Table({
    width: { size: 9360, type: WidthType.DXA },
    columnWidths: [9360],
    rows: [new TableRow({
      children: [new TableCell({
        borders: NO_BORDERS,
        width: { size: 9360, type: WidthType.DXA },
        shading: { fill: fillColor, type: ShadingType.CLEAR },
        margins: { top: 160, bottom: 160, left: 240, right: 240 },
        children: [
          new Paragraph({
            spacing: { before: 40, after: 80 },
            children: [
              new TextRun({ text: "QUOTE: ", bold: true, font: "Arial", size: 22, color: labelColor }),
              new TextRun({ text: `"${quote}"`, italics: true, font: "Arial", size: 22, color: DARK })
            ]
          }),
          new Paragraph({
            spacing: { before: 40, after: 40 },
            children: [
              new TextRun({ text: "ANALYSIS: ", bold: true, font: "Arial", size: 22, color: labelColor }),
              new TextRun({ text: analysis, font: "Arial", size: 22, color: DARK })
            ]
          })
        ]
      })]
    })]
  });
}

function dataTable(col1Header, col2Header, rows, fillColor) {
  const headerRow = new TableRow({
    children: [
      new TableCell({
        borders: BORDERS, width: { size: 3120, type: WidthType.DXA },
        shading: { fill: BLUE, type: ShadingType.CLEAR },
        margins: { top: 80, bottom: 80, left: 120, right: 120 },
        children: [new Paragraph({ children: [new TextRun({ text: col1Header, bold: true, color: "FFFFFF", font: "Arial", size: 22 })] })]
      }),
      new TableCell({
        borders: BORDERS, width: { size: 6240, type: WidthType.DXA },
        shading: { fill: BLUE, type: ShadingType.CLEAR },
        margins: { top: 80, bottom: 80, left: 120, right: 120 },
        children: [new Paragraph({ children: [new TextRun({ text: col2Header, bold: true, color: "FFFFFF", font: "Arial", size: 22 })] })]
      })
    ]
  });
  const dataRows = rows.map(([c1, c2], i) => new TableRow({
    children: [
      new TableCell({
        borders: BORDERS, width: { size: 3120, type: WidthType.DXA },
        shading: { fill: i % 2 === 0 ? fillColor : "FFFFFF", type: ShadingType.CLEAR },
        margins: { top: 80, bottom: 80, left: 120, right: 120 },
        children: [new Paragraph({ children: [new TextRun({ text: c1, bold: true, font: "Arial", size: 22 })] })]
      }),
      new TableCell({
        borders: BORDERS, width: { size: 6240, type: WidthType.DXA },
        shading: { fill: i % 2 === 0 ? "FFFFFF" : "FAFAFA", type: ShadingType.CLEAR },
        margins: { top: 80, bottom: 80, left: 120, right: 120 },
        children: [new Paragraph({ children: [new TextRun({ text: c2, font: "Arial", size: 22 })] })]
      })
    ]
  }));
  return new Table({
    width: { size: 9360, type: WidthType.DXA },
    columnWidths: [3120, 6240],
    rows: [headerRow, ...dataRows]
  });
}

function sp(before = 120) {
  return new Paragraph({ spacing: { before, after: 0 }, children: [new TextRun("")] });
}

function pb() {
  return new Paragraph({ children: [new PageBreak()] });
}

const doc = new Document({
  numbering: {
    config: [{
      reference: "bullets",
      levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
        style: { paragraph: { indent: { left: 720, hanging: 360 } } } }]
    }]
  },
  styles: {
    default: { document: { run: { font: "Arial", size: 22 } } },
    paragraphStyles: [
      { id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 36, bold: true, font: "Arial" },
        paragraph: { spacing: { before: 320, after: 120 }, outlineLevel: 0 } },
      { id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 28, bold: true, font: "Arial" },
        paragraph: { spacing: { before: 240, after: 80 }, outlineLevel: 1 } }
    ]
  },
  sections: [{
    properties: {
      page: {
        size: { width: 11906, height: 16838 },
        margin: { top: 1080, right: 1080, bottom: 1080, left: 1080 }
      }
    },
    children: [

      // TITLE
      sp(480),
      new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 0, after: 80 }, children: [new TextRun({ text: "GCSE English Literature", bold: true, size: 52, color: BLUE, font: "Arial" })] }),
      new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 0, after: 60 }, children: [new TextRun({ text: "AQA Paper 1 — Revision Notes", bold: true, size: 36, color: MID_GREY, font: "Arial" })] }),
      new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 0, after: 320 }, children: [new TextRun({ text: "Romeo & Juliet  |  A Christmas Carol", size: 28, color: MID_GREY, font: "Arial", italics: true })] }),
      colourBox([
        new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 60, after: 40 }, children: [new TextRun({ text: "1 hour 45 minutes  •  Section A: Romeo & Juliet (45 min)  •  Section B: A Christmas Carol (45 min)", font: "Arial", size: 22, color: BLUE, bold: true })] }),
        new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 0, after: 60 }, children: [new TextRun({ text: "Each question: extract + wider text  •  30 marks + 4 SPaG per section", font: "Arial", size: 22, color: DARK })] }),
      ], LIGHT_BLUE),

      pb(),

      // ESSAY TECHNIQUE
      heading1("Essay Technique", BLUE),
      sp(80),
      heading2("The PEAC Paragraph Formula"),
      colourBox([
        new Paragraph({ spacing: { before: 60, after: 40 }, children: [new TextRun({ text: "P — Point: ", bold: true, font: "Arial", size: 22, color: BLUE }), new TextRun({ text: "Make a clear argument linked to the question", font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 0, after: 40 }, children: [new TextRun({ text: "E — Evidence: ", bold: true, font: "Arial", size: 22, color: BLUE }), new TextRun({ text: "Embed a short, precise quote", font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 0, after: 40 }, children: [new TextRun({ text: "A — Analysis: ", bold: true, font: "Arial", size: 22, color: BLUE }), new TextRun({ text: "Zoom in on specific words — what does the language DO? Ask: why THIS word?", font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 0, after: 60 }, children: [new TextRun({ text: "C — Context: ", bold: true, font: "Arial", size: 22, color: BLUE }), new TextRun({ text: "Link to the writer's intentions OR social/historical context — weave it in naturally", font: "Arial", size: 22 })] }),
      ], LIGHT_BLUE),

      sp(160),
      heading2("Model Introduction Structure"),
      bullet("Directly answer the question in your FIRST sentence — never retell the story"),
      bullet("Name the writer and use the title of the text"),
      bullet("State your overall line of argument — what are you going to argue?"),
      bullet("Optionally: drop in one brief context point"),
      sp(80),
      colourBox([
        new Paragraph({ spacing: { before: 60, after: 40 }, children: [new TextRun({ text: "Example question: ", bold: true, font: "Arial", size: 22, color: GOLD }), new TextRun({ text: "How does Shakespeare present the theme of conflict in Romeo and Juliet?", italics: true, font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 40, after: 60 }, children: [new TextRun({ text: "Model intro: ", bold: true, font: "Arial", size: 22, color: GOLD }), new TextRun({ text: "In Romeo and Juliet, Shakespeare presents conflict as an inescapable force that corrupts every aspect of Veronese society — from the political to the personal. Rather than portraying conflict as merely physical violence, Shakespeare suggests it is a disease embedded in language, honour and family loyalty, ultimately making tragedy inevitable. Written for an Elizabethan audience who valued social order, Shakespeare uses the feud to explore the destructive consequences of unchecked hatred.", font: "Arial", size: 22 })] }),
      ], LIGHT_GOLD),

      sp(160),
      heading2("Weak vs Grade 9 Analysis"),
      colourBox([
        new Paragraph({ spacing: { before: 60, after: 40 }, children: [new TextRun({ text: "WEAK: ", bold: true, font: "Arial", size: 22, color: RED }), new TextRun({ text: '"This shows Scrooge is cold and does not care about people."', italics: true, font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 40, after: 60 }, children: [new TextRun({ text: "GRADE 9: ", bold: true, font: "Arial", size: 22, color: GREEN }), new TextRun({ text: '"The simile \'solitary as an oyster\' is carefully chosen — an oyster is not just alone, it is sealed shut, suggesting Scrooge has actively closed himself off. The hardness of the shell implies he has built a deliberate defence against human warmth, which Dickens frames as self-imposed imprisonment rather than mere personality."', italics: true, font: "Arial", size: 22 })] }),
      ], "F5F5F5"),

      sp(160),
      heading2("Key Terminology"),
      dataTable("Term", "What it means / why it matters", [
        ["Metaphor / Simile", "Direct or comparative image — ask: what does the comparison imply about the subject?"],
        ["Oxymoron", "Two contradictory ideas together — shows internal conflict or impossibility"],
        ["Dramatic irony", "Audience knows something a character doesn't — creates dread or tension"],
        ["Foreshadowing", "Hints at future events — shows inevitability or warns the reader"],
        ["Chiasmus", "Reversed grammatical structure (e.g. 'violent delights... violent ends') — mirrors ideas"],
        ["Tripling", "Three words/phrases for emphasis — creates sense of completeness or accumulation"],
        ["Rhetorical question", "Question for effect, not answer — challenges the audience or implies an obvious answer"],
        ["Symbolism", "Object/person represents a wider idea — always ask: what does it stand for?"],
      ], LIGHT_BLUE),

      pb(),

      // ROMEO AND JULIET
      heading1("Romeo & Juliet — Shakespeare", RED),
      sp(80),
      heading2("Key Context Points"),
      colourBox([
        bullet("Elizabethan audiences believed stars literally governed fate — 'star-crossed' was not just a metaphor"),
        bullet("Patriarchal society: women were property of fathers, then husbands — Juliet defying this is radical"),
        bullet("Honour culture: families defended reputation with violence — the feud is about pride, not logic"),
        bullet("Shakespeare wrote for a mixed audience — groundlings stood, wealthy sat in galleries"),
        bullet("The play is a warning about how hatred destroys even the innocent"),
      ], LIGHT_RED),

      sp(160),
      heading2("Key Themes & Characters"),
      dataTable("Theme / Character", "Key idea for essays", [
        ["Fate & Inevitability", "The lovers are doomed from the start — Prologue reveals the ending immediately, shifting focus from what to why"],
        ["Love", "Presented as intense, consuming and dangerous — not purely romantic. Speed of love mirrors its danger"],
        ["Conflict", "Physical, verbal and internal — the feud corrupts all of Verona; passion itself is a form of violence"],
        ["Family & Society", "Family loyalty traps individuals — love vs duty is the central impossible tension"],
        ["Romeo", "Impulsive, passionate, poetic — acts before thinking; his defiance of fate fulfils it"],
        ["Juliet", "More rational than Romeo; defies patriarchy; matures rapidly; arguably the true protagonist"],
        ["Friar Lawrence", "Voice of reason whose good intentions cause harm — represents the failure of moderation"],
        ["Mercutio", "Wit masks tragedy — his death is the turning point; the play darkens permanently after his exit"],
      ], LIGHT_RED),

      sp(160),
      heading2("Quotes & Grade 9 Analysis"),

      heading3("Fate", RED),
      quoteBox("A pair of star-crossed lovers take their life",
        "Placed in the Prologue, Shakespeare tells the audience the ending before the play begins. 'Star-crossed' implies the lovers work against the movement of the heavens — in Elizabethan belief, this was literal cosmology, not metaphor. By revealing the ending immediately, Shakespeare shifts the tragedy from what happens to why. The audience watches with dread rather than suspense — this is a play about inevitability, not bad luck.",
        LIGHT_RED, RED),

      sp(120),
      heading3("Love", RED),
      quoteBox("It is the east, and Juliet is the sun",
        "Shakespeare uses celestial imagery to elevate Juliet beyond the earthly — Romeo compares her not to a person or object, but to the sun itself, the source of all light and life. The hyperbole is deliberate: young love is presented as all-consuming and irrational. There is also dramatic irony — the sun rises but also sets, foreshadowing the tragedy to come. The audience understands what Romeo cannot.",
        LIGHT_RED, RED),

      sp(120),
      heading3("Conflict / Danger of Passion", RED),
      quoteBox("These violent delights have violent ends",
        "Friar Lawrence's warning uses chiasmus — 'violent' frames the sentence on both sides, trapping 'delights' within destruction. Shakespeare uses the Friar as a voice of reason, but his warnings go unheeded, implicating haste as much as fate in the tragedy. The word 'violent' suggests passion itself is dangerous — Shakespeare warns that extremity of any kind carries the seeds of its own destruction.",
        LIGHT_RED, RED),

      sp(120),
      heading3("Juliet's Agency", RED),
      quoteBox("What's in a name? That which we call a rose by any other name would smell as sweet",
        "Juliet's rhetorical question challenges the arbitrary nature of the feud — she is more philosophically clear-eyed than Romeo. The rose metaphor argues identity is intrinsic, not named — a radical position for a 13-year-old girl in a patriarchal society. Shakespeare gives Juliet remarkable intellectual agency here, arguably making her the more rational of the two lovers. An Elizabethan audience would have been struck by a young woman dismantling social convention so fluently.",
        LIGHT_RED, RED),

      sp(120),
      heading3("Romeo's Impulsiveness", RED),
      quoteBox("Then I defy you, stars!",
        "Romeo's outburst on hearing of Juliet's death is his most defiant moment — but also his most self-destructive. The exclamation shows passion overriding reason entirely. Crucially, by defying fate he fulfils it — rushing to the tomb is the very action that causes the double death. Shakespeare uses dramatic irony: the stars he defies were going to kill him anyway; his defiance simply removes any chance of survival.",
        LIGHT_RED, RED),

      sp(120),
      heading3("Love vs Hate / Central Tension", RED),
      quoteBox("My only love sprung from my only hate",
        "Juliet's oxymoron captures the central tension of the play in a single line. 'Only' appears twice, emphasising that both her love and her hatred are absolute — there is no middle ground in Verona. The compression of the line mirrors the impossibility of her situation: love and hate are not opposites here but intertwined, which is exactly what makes the tragedy unavoidable. Shakespeare shows that the feud does not just kill people — it poisons the capacity for love itself.",
        LIGHT_RED, RED),

      pb(),

      // A CHRISTMAS CAROL
      heading1("A Christmas Carol — Dickens", GREEN),
      sp(80),
      heading2("Key Context Points"),
      colourBox([
        bullet("Dickens grew up in poverty — his father was imprisoned for debt; young Dickens worked in a blacking factory"),
        bullet("The Poor Law Amendment Act (1834) forced the poor into workhouses — deliberately harsh conditions"),
        bullet("Victorian Christmas was being reinvented — Dickens helped shape it as a time of charity and community"),
        bullet("Written in 6 weeks in 1843 — essentially a political pamphlet dressed as a ghost story"),
        bullet("Scrooge's redemption follows a Christian resurrection narrative — a Victorian audience would recognise this"),
        bullet("Dickens is directly attacking wealthy Victorians who ignored suffering around them"),
      ], LIGHT_GREEN),

      sp(160),
      heading2("Key Themes & Characters"),
      dataTable("Theme / Character", "Key idea for essays", [
        ["Redemption", "Scrooge's transformation is the heart of the novella — Dickens argues change is always possible"],
        ["Social Responsibility", "Dickens attacks Victorian indifference to poverty — wealth without compassion is moral failure"],
        ["Christmas & Generosity", "Christmas represents warmth, community and charity — the opposite of Scrooge's opening values"],
        ["Past, Present & Future", "Each ghost = a relationship with time. Past: shapes us. Present: our choice. Future: warning"],
        ["Isolation vs Family", "Scrooge is cut off from love; the Cratchits show happiness comes from togetherness, not wealth"],
        ["Scrooge", "Begins: miserly, isolated, fearful. Ends: generous, joyful. His arc IS the whole story"],
        ["Fred", "Unconditional Christmas spirit — generous even when mocked; foil to Scrooge"],
        ["Bob Cratchit", "The exploited working class — loyal and warm despite poverty; Dickens' moral compass"],
        ["Tiny Tim", "Symbol of innocent vulnerability — represents the poor whose suffering indicts society"],
        ["Jacob Marley", "Warning of what Scrooge could become — his chains represent the sins of ignoring others"],
      ], LIGHT_GREEN),

      sp(160),
      heading2("Quotes & Grade 9 Analysis"),

      heading3("Isolation / Scrooge's Character", GREEN),
      quoteBox("Solitary as an oyster",
        "An oyster is sealed shut by its own shell — Dickens uses this simile to suggest Scrooge's isolation is self-imposed. The hardness of the image implies a deliberate defence against human connection. A Victorian reader would associate oysters with the cold, dark sea, reinforcing Scrooge's emotional bleakness. Dickens frames isolation not as circumstance but as a choice — and therefore something that can be undone.",
        LIGHT_GREEN, GREEN),

      sp(120),
      heading3("Social Responsibility / Indifference to the Poor", GREEN),
      quoteBox("Are there no prisons? Are there no workhouses?",
        "The rhetorical questions mirror the dismissive logic of Victorian upper classes who believed poverty was a personal failing. Dickens uses Scrooge as a mouthpiece for the attitudes he is attacking — the repetition is deliberately cold and bureaucratic, stripping the poor of humanity. A contemporary reader would recognise this as a direct criticism of the Poor Law Amendment Act of 1834. Scrooge does not just ignore suffering — he redirects it.",
        LIGHT_GREEN, GREEN),

      sp(120),
      heading3("Redemption / Scrooge's Transformation", GREEN),
      quoteBox("I am as light as a feather, I am as happy as an angel, I am as merry as a schoolboy",
        "The tripling of similes reflects Scrooge's complete transformation — the accumulation mirrors his overwhelming joy, as though one comparison cannot contain it. The progression from 'feather' (physical lightness) to 'angel' (spiritual elevation) to 'schoolboy' (emotional innocence) suggests Dickens sees redemption as a return to a purer self. A Victorian Christian audience would read this as a resurrection narrative.",
        LIGHT_GREEN, GREEN),

      sp(120),
      heading3("Social Responsibility — Marley's Warning", GREEN),
      quoteBox("Mankind was my business. The common welfare was my business",
        "The repetition of 'my business' directly inverts Scrooge's earlier obsession with financial business. Dickens uses Marley as a moral mirror — showing what Scrooge will become. The word 'mankind' is deliberately vast, suggesting social responsibility is not optional charity but a fundamental human duty. Dickens, who had himself grown up in poverty, argues that wealth without compassion is a form of moral failure.",
        LIGHT_GREEN, GREEN),

      sp(120),
      heading3("Tiny Tim / The Vulnerable Poor", GREEN),
      quoteBox("God bless us, every one",
        "The inclusive 'every one' is Dickens' most pointed political statement — Tim, the most vulnerable character, offers universal blessing, including to those who would deny him charity. The simplicity of the language is deliberate: Dickens strips away complexity to make the moral argument unanswerable. Tim functions less as a character and more as a symbol — he represents the innocent poor whose suffering indicts a whole society.",
        LIGHT_GREEN, GREEN),

      sp(120),
      heading3("Christmas / Spirit of Generosity", GREEN),
      quoteBox("I will honour Christmas in my heart, and try to keep it all the year",
        "Scrooge's vow uses the verb 'honour' — a word associated with duty and respect, elevating Christmas beyond mere celebration to a moral code. The phrase 'all the year' is key: Dickens argues generosity must not be seasonal but a permanent way of living. This is the climax of Scrooge's transformation and the clearest statement of Dickens' own political message to his Victorian readers.",
        LIGHT_GREEN, GREEN),

      sp(240),
      colourBox([
        new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 60, after: 80 }, children: [new TextRun({ text: "Exam Day Reminders", bold: true, font: "Arial", size: 28, color: BLUE })] }),
        new Paragraph({ spacing: { before: 0, after: 40 }, children: [new TextRun({ text: "✓  Analyse the extract AND the wider text — both are required", font: "Arial", size: 22, bold: true })] }),
        new Paragraph({ spacing: { before: 0, after: 40 }, children: [new TextRun({ text: "✓  Zoom in on specific words — don't just say what, say HOW and WHY", font: "Arial", size: 22, bold: true })] }),
        new Paragraph({ spacing: { before: 0, after: 40 }, children: [new TextRun({ text: "✓  Weave in context naturally — don't bolt it on at the end of a paragraph", font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 0, after: 40 }, children: [new TextRun({ text: "✓  Answer the question directly from your very first sentence", font: "Arial", size: 22 })] }),
        new Paragraph({ spacing: { before: 0, after: 60 }, children: [new TextRun({ text: "✓  Leave 2-3 minutes to check SPaG — that's 4 free marks per essay", font: "Arial", size: 22 })] }),
      ], LIGHT_BLUE),
    ]
  }]
});

Packer.toBuffer(doc).then(buffer => {
  fs.writeFileSync("/mnt/user-data/outputs/GCSE_English_Lit_Revision_Notes.docx", buffer);
  console.log("Done!");
}).catch(e => { console.error(e); process.exit(1); });
Editor is loading...
Leave a Comment