slidict 0.5.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc5350820094f49312526c30c254f437edd49374ac0202ba99067637a70dd331
4
- data.tar.gz: 130980c85ff4a85a0189b95fddc825ea30eeae131e1549d83e80cee1ae5ba392
3
+ metadata.gz: ab47129a915cbf21d2a573c0f1d3f9f9b654eb86a6a4226261a94fc44a60ba16
4
+ data.tar.gz: f0ab819d3077c1bfa36f268dc06939c7f02bd483649be86d360d5558a2dded34
5
5
  SHA512:
6
- metadata.gz: d27d844ad6ed53f6d860fe92e8614fad35e19caa10a9e5395b4eb6640c314a0224b0c32a5de612f13cababc8e438f61c1d6103d5a5c3a8133e2021eb67be6f73
7
- data.tar.gz: 241380442ea402ed968bbd7829ec8ec49446f70d7f80852d75248a829d041b09d7a9c62d9ead1341d49e6dd5beff152340c7766f822bd064c29a1e0c407fb200
6
+ metadata.gz: 173dc71c06cf303b382fe7527ec27c8ddb61a9c3ced94563914fe2b56121af308b8d3f6290597800c32086d6ba6b51e8dc91dc1128a6776abf8358e0e1a113dc
7
+ data.tar.gz: e76f87bdd14452ce271dfa20cf5f8af65c5f82a3b687b53958d8e8a2cf45f022b79ba0ee2dd2dc753a02b1dcb44c4032bee8bfcebb2adbaf7512e77dcba7d68a
@@ -0,0 +1,22 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR change, and why? -->
4
+
5
+ ## Version bump
6
+
7
+ This repository follows [Semantic Versioning](https://semver.org/) (see `AGENTS.md`).
8
+ Every PR is expected to update `lib/slidict/version.rb`, and CI fails when it does not.
9
+
10
+ - [ ] <!-- skip-version-check --> This PR does not require a version bump
11
+
12
+ <!--
13
+ Leave the box above unchecked and bump `lib/slidict/version.rb` in this PR.
14
+ Check it only when no release is needed (docs-only, CI-only, test-only changes, etc.).
15
+ Keep the `skip-version-check` comment intact — the CI check looks for it.
16
+ -->
17
+
18
+ ## Checklist
19
+
20
+ - [ ] `bundle exec rspec` passes
21
+ - [ ] `bundle exec rubocop` passes
22
+ - [ ] `README.md` updated if user-facing behavior changed
@@ -0,0 +1,70 @@
1
+ name: Version Check
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - reopened
8
+ - synchronize
9
+ - edited
10
+ - ready_for_review
11
+
12
+ permissions:
13
+ contents: read
14
+ pull-requests: read
15
+
16
+ jobs:
17
+ version-file:
18
+ name: Require version.rb update
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Require version.rb update or an explicit skip
23
+ env:
24
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25
+ REPO: ${{ github.repository }}
26
+ PR_NUMBER: ${{ github.event.pull_request.number }}
27
+ PR_BODY: ${{ github.event.pull_request.body }}
28
+ PR_ACTOR: ${{ github.event.pull_request.user.login }}
29
+ VERSION_FILE: lib/slidict/version.rb
30
+ run: |
31
+ set -euo pipefail
32
+
33
+ # Dependency update PRs are opened by bots that cannot fill in the
34
+ # pull request template, so they are exempt from this check.
35
+ case "$PR_ACTOR" in
36
+ 'dependabot[bot]' | 'github-actions[bot]')
37
+ echo "::notice::Skipping version check for bot author '${PR_ACTOR}'."
38
+ exit 0
39
+ ;;
40
+ esac
41
+
42
+ # The pull request template ships a checkbox carrying the
43
+ # `skip-version-check` marker, unchecked by default.
44
+ if printf '%s\n' "${PR_BODY:-}" |
45
+ grep -qiE '^[[:space:]]*[-*+][[:space:]]+\[[[:space:]]*x[[:space:]]*\].*skip-version-check'; then
46
+ echo "::notice::'${VERSION_FILE}' is not required: the skip-version-check box is checked."
47
+ exit 0
48
+ fi
49
+
50
+ changed_files="$(gh api --paginate "repos/${REPO}/pulls/${PR_NUMBER}/files" --jq '.[].filename')"
51
+
52
+ if printf '%s\n' "$changed_files" | grep -qxF "$VERSION_FILE"; then
53
+ echo "::notice::'${VERSION_FILE}' is updated in this pull request."
54
+ exit 0
55
+ fi
56
+
57
+ echo "::error::'${VERSION_FILE}' is not updated in this pull request."
58
+ {
59
+ echo "### Version check failed"
60
+ echo
61
+ echo "This pull request does not update \`${VERSION_FILE}\`."
62
+ echo
63
+ echo "Do one of the following:"
64
+ echo
65
+ echo "- Bump \`VERSION\` in \`${VERSION_FILE}\` following [SemVer](https://semver.org/) (see \`AGENTS.md\`), or"
66
+ echo "- Check the \"This PR does not require a version bump\" box in the pull request description."
67
+ echo
68
+ echo "Editing the description re-runs this check automatically."
69
+ } >> "$GITHUB_STEP_SUMMARY"
70
+ exit 1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.7.0] - 2026-07-30
4
+
5
+ - Add built-in SDS, DESC, AIDMA, TAPS, and FABE presentation methods.
6
+ - Add source-text slide generation through `--text`, `--text-file`, and the reusable
7
+ `Slidict::Generator` integration API.
3
8
  - Add `slidict init` to create a `.env` file (for `SLIDICT_LLM_*`, `SLIDICT_FRAMEWORK`,
4
9
  and `SLIDICT_METHOD`) and add it to `.gitignore`. `.env` is loaded automatically and
5
10
  fills in unset environment variables; CLI flags still take precedence.
data/README.md CHANGED
@@ -63,6 +63,34 @@ bin/slidict \
63
63
  --output slides.adoc
64
64
  ```
65
65
 
66
+ To create a presentation from an existing article, memo, or other prose, pass the
67
+ text directly or read it from a file. Source-text generation requires an LLM endpoint;
68
+ the first non-empty line is used as the topic when `--topic` is omitted. Slidict asks
69
+ the model to preserve the source's facts and examples instead of inventing claims.
70
+
71
+ ```bash
72
+ bin/slidict --text-file proposal.md \
73
+ --llm-base-url https://api.openai.com/v1 \
74
+ --llm-api-key "$OPENAI_API_KEY" --llm-model gpt-4o-mini
75
+
76
+ bin/slidict --text "Why our team should adopt automated accessibility testing ..." \
77
+ --llm-base-url http://localhost:11434/v1 --llm-api-key ollama --llm-model llama3
78
+ ```
79
+
80
+ Applications can use the same pipeline without CLI or filesystem side effects. The
81
+ result contains both the structured `deck` and rendered presentation `content`:
82
+
83
+ ```ruby
84
+ client = Slidict::Llm::Client.new(base_url: url, api_key: key, model: model)
85
+ result = Slidict::Generator.new(client: client).generate(
86
+ text: article,
87
+ framework: "slidev",
88
+ language: "Japanese"
89
+ )
90
+ result.deck # => Slidict::Deck
91
+ result.content # => Slidev source
92
+ ```
93
+
66
94
  Add `--publish` to also save the generated slides to slidict.io as a draft (requires
67
95
  `slidict auth` first). Pass `--slide-id` to edit an existing draft instead of creating a
68
96
  new one:
@@ -271,10 +299,12 @@ We optimize for communication, not decoration.
271
299
 
272
300
  ## Presentation methods
273
301
 
274
- Use `--method` to generate slides with a specific narrative structure, such as SCQA, PREP, or Pyramid Principle.
302
+ Use `--method` to generate slides with a specific narrative structure. Built-in methods include SDS, PREP, DESC,
303
+ AIDMA, TAPS, FABE, SCQA, and Pyramid Principle.
275
304
 
276
305
  ```bash
277
306
  bin/slidict --method scqa --topic "Database migration plan"
307
+ bin/slidict --method aidma --topic "Product launch"
278
308
  bin/slidict list-methods
279
309
  bin/slidict show-method scqa
280
310
  ```
@@ -0,0 +1,35 @@
1
+ id: aidma
2
+ name: AIDMA
3
+ category: marketing
4
+ description: Attention, Interest, Desire, Memory, Action structure for guiding an audience from awareness to action.
5
+ locale: en
6
+ suitable_for:
7
+ - Marketing presentations
8
+ - Product and service pitches
9
+ - Campaign or launch proposals
10
+ slides:
11
+ - title: Attention
12
+ role: Capture attention with an audience-relevant hook.
13
+ instructions: Open with a striking fact, question, or situation connected to the audience's needs.
14
+ - title: Interest
15
+ role: Build interest by showing why the subject is relevant.
16
+ instructions: Connect the offer or idea to a recognizable problem, opportunity, or aspiration.
17
+ - title: Desire
18
+ role: Turn interest into a preference for the proposed solution.
19
+ instructions: Show concrete benefits and help the audience imagine the improved outcome.
20
+ - title: Memory
21
+ role: Make the key message easy to recall.
22
+ instructions: Reinforce one distinctive promise with memorable evidence, phrasing, or imagery.
23
+ - title: Action
24
+ role: Prompt the audience to take a clear next step.
25
+ instructions: State one specific action, remove ambiguity, and explain what happens next.
26
+ ai_instructions:
27
+ - Move through the AIDMA stages in order without asking for action too early.
28
+ - Frame benefits from the audience's point of view.
29
+ - Keep the memorable promise consistent with the evidence and call to action.
30
+ review_checklist:
31
+ - Does the opening earn the target audience's attention?
32
+ - Does interest develop into a concrete desire?
33
+ - Is the central promise distinctive and memorable?
34
+ - Is the requested action specific and easy to understand?
35
+ references: []
@@ -0,0 +1,32 @@
1
+ id: desc
2
+ name: DESC
3
+ category: assertive-communication
4
+ description: Describe, Express, Specify, Consequences structure for proposing a constructive change or resolving conflict.
5
+ locale: en
6
+ suitable_for:
7
+ - Feedback and difficult conversations
8
+ - Conflict resolution
9
+ - Requests for behavioral or process change
10
+ slides:
11
+ - title: Describe
12
+ role: Describe the situation or behavior objectively.
13
+ instructions: State observable facts without blame, assumptions, or judgment.
14
+ - title: Express
15
+ role: Explain the impact and the speaker's perspective or feelings.
16
+ instructions: Use specific first-person language to show why the situation matters.
17
+ - title: Specify
18
+ role: Request a concrete and achievable change.
19
+ instructions: Define the desired behavior, owner, and timing so the request is actionable.
20
+ - title: Consequences
21
+ role: Clarify the positive outcomes of the change and the implications of inaction.
22
+ instructions: Emphasize realistic benefits and consequences rather than threats.
23
+ ai_instructions:
24
+ - Separate observable facts from interpretations and emotions.
25
+ - Keep the tone respectful, direct, and solution-oriented.
26
+ - Make the requested change specific enough to act on.
27
+ review_checklist:
28
+ - Is the description factual and nonjudgmental?
29
+ - Is the impact expressed clearly from the speaker's perspective?
30
+ - Is the requested change concrete and achievable?
31
+ - Are the consequences realistic and constructive?
32
+ references: []
@@ -0,0 +1,32 @@
1
+ id: fabe
2
+ name: FABE
3
+ category: sales
4
+ description: Features, Advantages, Benefits, Evidence structure for connecting an offering's capabilities to credible customer value.
5
+ locale: en
6
+ suitable_for:
7
+ - Sales presentations
8
+ - Product demonstrations
9
+ - Solution comparisons
10
+ slides:
11
+ - title: Features
12
+ role: Introduce the relevant capabilities or attributes of the offering.
13
+ instructions: Select only features connected to the audience's needs and describe them precisely.
14
+ - title: Advantages
15
+ role: Explain how those features perform better or differently.
16
+ instructions: Compare the capabilities with the current approach or alternatives without unsupported claims.
17
+ - title: Benefits
18
+ role: Translate the advantages into outcomes the audience values.
19
+ instructions: State tangible functional or emotional value in the audience's terms.
20
+ - title: Evidence
21
+ role: Prove the promised benefits with credible support.
22
+ instructions: Use relevant data, demonstrations, testimonials, or case results and identify their context.
23
+ ai_instructions:
24
+ - Maintain a clear chain from each feature to its advantage, benefit, and evidence.
25
+ - Prioritize audience value over a long inventory of specifications.
26
+ - Avoid claims that the evidence does not substantiate.
27
+ review_checklist:
28
+ - Are the selected features relevant to the audience's needs?
29
+ - Are advantages differentiated clearly and fairly?
30
+ - Are benefits expressed as audience outcomes?
31
+ - Is every important claim supported by credible evidence?
32
+ references: []
@@ -0,0 +1,28 @@
1
+ id: sds
2
+ name: SDS
3
+ category: concise-communication
4
+ description: Summary, Details, Summary structure for communicating a message clearly and memorably.
5
+ locale: en
6
+ suitable_for:
7
+ - Short presentations and status updates
8
+ - Explanations that need a clear takeaway
9
+ - Messages for time-constrained audiences
10
+ slides:
11
+ - title: Summary
12
+ role: State the central message or conclusion at the outset.
13
+ instructions: Give the audience a concise overview of what they should understand or remember.
14
+ - title: Details
15
+ role: Support the opening summary with the essential facts, reasoning, or examples.
16
+ instructions: Present only the details needed to substantiate the central message, in a logical order.
17
+ - title: Summary Revisited
18
+ role: Reinforce the central message after the supporting detail.
19
+ instructions: Restate the takeaway in fresh, concise language and connect it to the desired response.
20
+ ai_instructions:
21
+ - Preserve the Summary, Details, Summary sequence.
22
+ - Keep the opening and closing summaries consistent while avoiding word-for-word repetition.
23
+ - Include only details that directly support the central message.
24
+ review_checklist:
25
+ - Is the central message clear in the opening summary?
26
+ - Do all details support that message?
27
+ - Does the closing summary reinforce the intended takeaway?
28
+ references: []
@@ -0,0 +1,32 @@
1
+ id: taps
2
+ name: TAPS
3
+ category: problem-solving
4
+ description: To Be, As Is, Problem, Solution structure for defining a desired state and the change needed to reach it.
5
+ locale: en
6
+ suitable_for:
7
+ - Improvement proposals
8
+ - Transformation roadmaps
9
+ - Problem-solving presentations
10
+ slides:
11
+ - title: To Be
12
+ role: Define the desired future state and its success criteria.
13
+ instructions: Describe a concrete, audience-relevant outcome rather than a vague aspiration.
14
+ - title: As Is
15
+ role: Establish the current state with objective evidence.
16
+ instructions: Show the present performance or behavior using facts that can be compared with the desired state.
17
+ - title: Problem
18
+ role: Identify the gap and the factors preventing progress.
19
+ instructions: Explain the most important root cause or barrier, not merely its symptoms.
20
+ - title: Solution
21
+ role: Present the actions that will close the gap.
22
+ instructions: Connect each proposed action to the identified problem and specify the immediate next step.
23
+ ai_instructions:
24
+ - Make the gap between To Be and As Is explicit and measurable where possible.
25
+ - Distinguish root causes from symptoms.
26
+ - Ensure the solution directly addresses the stated problem.
27
+ review_checklist:
28
+ - Is the desired state concrete and relevant?
29
+ - Is the current state supported by evidence?
30
+ - Does the problem explain the gap between the two states?
31
+ - Does the solution address the root cause and define a next step?
32
+ references: []
@@ -10,11 +10,13 @@ gem only loads, validates, and applies that data.
10
10
  bin/slidict new --method prep --topic "New onboarding flow"
11
11
  bin/slidict --method scqa --topic "Database migration plan"
12
12
  bin/slidict --method pyramid --topic "FY roadmap recommendation"
13
+ bin/slidict --method fabe --topic "Customer analytics platform"
13
14
  bin/slidict list-methods
14
15
  bin/slidict show-method scqa
15
16
  ```
16
17
 
17
- Built-in methods currently include SCQA, PREP, and Pyramid Principle.
18
+ Built-in methods currently include SDS, PREP, DESC, AIDMA, TAPS, FABE, SCQA,
19
+ and Pyramid Principle.
18
20
 
19
21
  ## Architecture
20
22
 
@@ -32,9 +34,14 @@ This keeps contribution review small: a new built-in method is usually one YAML
32
34
 
33
35
  ```text
34
36
  data/slidict/methods/
37
+ aidma.yml
38
+ desc.yml
39
+ fabe.yml
35
40
  prep.yml
36
41
  pyramid.yml
37
42
  scqa.yml
43
+ sds.yml
44
+ taps.yml
38
45
  lib/slidict/presentation_method.rb
39
46
  ```
40
47
 
@@ -32,6 +32,8 @@ module Slidict
32
32
  flag "--duration", arg: "TEXT", desc: 'Presentation length, for example "5 minutes"'
33
33
  flag "--audience", arg: "TEXT", desc: "Target audience"
34
34
  flag "--goal", arg: "TEXT", desc: "Desired audience takeaway or action"
35
+ flag "--text", arg: "TEXT", desc: "Source text to turn into slides"
36
+ flag "--text-file", arg: "PATH", desc: "Read source text from a file"
35
37
  flag "--framework", arg: "NAME",
36
38
  desc: -> { "#{Output::Format.names.join(", ")} (default: slidev)\n(env: SLIDICT_FRAMEWORK)" }
37
39
  flag "--method", arg: "ID", desc: "Presentation method, for example scqa, prep, or pyramid\n" \
@@ -73,17 +75,23 @@ module Slidict
73
75
  config = build_config(options)
74
76
  return print_available_models(config) if config.llm_enabled? && config.model.nil?
75
77
 
78
+ # Validate and read local input before making a network request. This
79
+ # keeps missing/empty source-file errors fast and deterministic.
80
+ options[:text] = read_source_text(options)
76
81
  client = llm_client_for(config)
77
82
  return FAILURE if client && !verify_connection(client)
78
83
 
84
+ raise ArgumentError, "--text and --text-file require an LLM endpoint" if options[:text] && !client
85
+
79
86
  questions = questions_for(client, options)
80
87
  deck = Deck.new(
81
- topic: ask(questions[:topic], options[:topic]),
82
- duration: ask(questions[:duration], options[:duration]),
83
- audience: ask(questions[:audience], options[:audience]),
84
- goal: ask(questions[:goal], options[:goal]),
88
+ topic: source_topic(options) || ask(questions[:topic], options[:topic]),
89
+ duration: options[:text] ? options[:duration] : ask(questions[:duration], options[:duration]),
90
+ audience: options[:text] ? options[:audience] : ask(questions[:audience], options[:audience]),
91
+ goal: options[:text] ? options[:goal] : ask(questions[:goal], options[:goal]),
85
92
  framework: options[:framework],
86
- presentation_method: options[:presentation_method]
93
+ presentation_method: options[:presentation_method],
94
+ source: options[:text]
87
95
  )
88
96
 
89
97
  if client
@@ -95,7 +103,8 @@ module Slidict
95
103
  end
96
104
  deck = Deck.new(
97
105
  topic: deck.topic, duration: deck.duration, audience: deck.audience, goal: deck.goal,
98
- framework: deck.framework, slides: slides, presentation_method: deck.presentation_method
106
+ framework: deck.framework, slides: slides, presentation_method: deck.presentation_method,
107
+ source: deck.source
99
108
  )
100
109
  end
101
110
 
@@ -117,6 +126,28 @@ module Slidict
117
126
 
118
127
  private
119
128
 
129
+ def read_source_text(options)
130
+ raise ArgumentError, "specify only one of --text or --text-file" if options[:text] && options[:text_file]
131
+ unless options[:text_file]
132
+ raise ArgumentError, "source text must not be empty" if options.key?(:text) && options[:text].to_s.strip.empty?
133
+
134
+ return options[:text]
135
+ end
136
+
137
+ File.read(options[:text_file]).tap do |text|
138
+ raise ArgumentError, "source text must not be empty" if text.strip.empty?
139
+ end
140
+ rescue Errno::ENOENT, Errno::EACCES => e
141
+ raise ArgumentError, "could not read #{options[:text_file]}: #{e.message}"
142
+ end
143
+
144
+ def source_topic(options)
145
+ return options[:topic] unless options[:topic].to_s.strip.empty?
146
+ return unless options[:text]
147
+
148
+ options[:text].each_line.map(&:strip).find { |line| !line.empty? }&.sub(/\A#+\s*/, "")
149
+ end
150
+
120
151
  def parse(argv)
121
152
  options = { framework: ENV["SLIDICT_FRAMEWORK"] || "slidev", method: ENV["SLIDICT_METHOD"] }
122
153
  args = argv.dup
@@ -370,7 +401,10 @@ module Slidict
370
401
 
371
402
  def fetch_value!(args, option)
372
403
  value = args.shift
373
- raise ArgumentError, "#{option} requires a value" if value.nil? || value.start_with?("-")
404
+ # Source prose can legitimately start with Markdown frontmatter or a
405
+ # list item. Other options retain the typo-friendly flag check.
406
+ missing = value.nil? || (value.start_with?("-") && option != "--text")
407
+ raise ArgumentError, "#{option} requires a value" if missing
374
408
 
375
409
  value
376
410
  end
@@ -389,6 +423,7 @@ module Slidict
389
423
  # left to ask, or a translation call fails -- this is a nicety, not
390
424
  # something worth aborting slide generation over.
391
425
  def questions_for(client, options)
426
+ return QUESTIONS if options[:text]
392
427
  return QUESTIONS unless client && options[:language]
393
428
 
394
429
  missing = QUESTIONS.select { |key, _| options[key].to_s.strip.empty? }
data/lib/slidict/deck.rb CHANGED
@@ -4,15 +4,17 @@ module Slidict
4
4
  Slide = Struct.new(:title, :bullets, keyword_init: true)
5
5
 
6
6
  class Deck
7
- attr_reader :topic, :duration, :audience, :goal, :framework, :presentation_method
7
+ attr_reader :topic, :duration, :audience, :goal, :framework, :presentation_method, :source
8
8
 
9
- def initialize(topic:, duration:, audience:, goal:, framework: "slidev", slides: nil, presentation_method: nil)
9
+ def initialize(topic:, duration:, audience:, goal:, framework: "slidev", slides: nil, presentation_method: nil,
10
+ source: nil)
10
11
  @topic = normalize(topic, fallback: "Untitled presentation")
11
12
  @duration = normalize(duration, fallback: "5 minutes")
12
13
  @audience = normalize(audience, fallback: "general audience")
13
14
  @goal = normalize(goal, fallback: "understand the key message")
14
15
  @framework = normalize(framework, fallback: "slidev").downcase
15
16
  @presentation_method = presentation_method
17
+ @source = source.to_s.strip
16
18
  @slides = slides
17
19
  end
18
20
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Slidict
4
+ # Framework-independent application API for integrations such as slidict.io.
5
+ # It turns source prose into both a Deck and presentation source without
6
+ # involving CLI input/output or the filesystem.
7
+ class Generator
8
+ Result = Struct.new(:deck, :content, keyword_init: true)
9
+
10
+ def initialize(client:, renderer: Output::Renderer.new)
11
+ @client = client
12
+ @renderer = renderer
13
+ end
14
+
15
+ def generate(text:, topic: nil, duration: nil, audience: nil, goal: nil,
16
+ framework: "slidev", language: nil, presentation_method: nil)
17
+ source = text.to_s.strip
18
+ raise ArgumentError, "text must not be empty" if source.empty?
19
+
20
+ deck = Deck.new(
21
+ topic: topic || title_from(source),
22
+ duration: duration,
23
+ audience: audience,
24
+ goal: goal || "communicate the source text clearly",
25
+ framework: framework,
26
+ presentation_method: presentation_method,
27
+ source: source
28
+ )
29
+ slides = @client.generate_slides(deck, language: language)
30
+ generated_deck = Deck.new(
31
+ topic: deck.topic, duration: deck.duration, audience: deck.audience, goal: deck.goal,
32
+ framework: deck.framework, slides: slides, presentation_method: deck.presentation_method,
33
+ source: source
34
+ )
35
+
36
+ Result.new(deck: generated_deck, content: @renderer.render(generated_deck))
37
+ end
38
+
39
+ private
40
+
41
+ def title_from(source)
42
+ source.each_line.map(&:strip).find { |line| !line.empty? }&.sub(/\A#+\s*/, "")
43
+ end
44
+ end
45
+ end
@@ -75,6 +75,7 @@ module Slidict
75
75
  Audience: #{deck.audience}
76
76
  Goal: #{deck.goal}
77
77
  #{method_prompt_for(deck)}
78
+ #{source_prompt_for(deck)}
78
79
 
79
80
  Return one slide for each required slide role when a presentation method is
80
81
  provided; otherwise return exactly 5 slides. Each item must be an object with
@@ -84,6 +85,19 @@ module Slidict
84
85
  PROMPT
85
86
  end
86
87
 
88
+ def source_prompt_for(deck)
89
+ return "" if deck.source.empty?
90
+
91
+ <<~SOURCE
92
+ Source text:
93
+ <source>
94
+ #{deck.source}
95
+ </source>
96
+ Base the presentation on the source text. Identify its central message,
97
+ preserve important facts and examples, and do not invent unsupported claims.
98
+ SOURCE
99
+ end
100
+
87
101
  def language_instruction_for(language)
88
102
  return "" unless language
89
103
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Slidict
4
- VERSION = "0.5.3"
4
+ VERSION = "0.7.0"
5
5
  end
data/lib/slidict.rb CHANGED
@@ -20,6 +20,7 @@ require_relative "slidict/lint/slide_parser"
20
20
  require_relative "slidict/llm/client"
21
21
  require_relative "slidict/output/format"
22
22
  require_relative "slidict/output/renderer"
23
+ require_relative "slidict/generator"
23
24
  require_relative "slidict/presentation_method"
24
25
  require_relative "slidict/version"
25
26
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slidict
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Abe
@@ -60,11 +60,13 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - ".github/dependabot.yml"
63
+ - ".github/pull_request_template.md"
63
64
  - ".github/release-drafter.yml"
64
65
  - ".github/workflows/bump-version.yml"
65
66
  - ".github/workflows/changelog.yml"
66
67
  - ".github/workflows/gem-push.yml"
67
68
  - ".github/workflows/test.yml"
69
+ - ".github/workflows/version-check.yml"
68
70
  - AGENTS.md
69
71
  - CHANGELOG.md
70
72
  - CODE_OF_CONDUCT.md
@@ -72,9 +74,14 @@ files:
72
74
  - LICENSE.txt
73
75
  - README.md
74
76
  - Rakefile
77
+ - data/slidict/methods/aidma.yml
78
+ - data/slidict/methods/desc.yml
79
+ - data/slidict/methods/fabe.yml
75
80
  - data/slidict/methods/prep.yml
76
81
  - data/slidict/methods/pyramid.yml
77
82
  - data/slidict/methods/scqa.yml
83
+ - data/slidict/methods/sds.yml
84
+ - data/slidict/methods/taps.yml
78
85
  - docs/demo-methods.gif
79
86
  - docs/demo-methods.tape
80
87
  - docs/demo.gif
@@ -92,6 +99,7 @@ files:
92
99
  - lib/slidict/external/slidict_io/auth.rb
93
100
  - lib/slidict/external/slidict_io/client.rb
94
101
  - lib/slidict/external/slidict_io/credentials.rb
102
+ - lib/slidict/generator.rb
95
103
  - lib/slidict/lint/finding.rb
96
104
  - lib/slidict/lint/linter.rb
97
105
  - lib/slidict/lint/renderer.rb