tomo2chin2 commited on
Commit
178eeaf
·
verified ·
1 Parent(s): e568bd6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +305 -63
app.py CHANGED
@@ -74,6 +74,65 @@ def generate_html_from_text(text, temperature=1.0, layout_type="standard"):
74
  - 小さめのアイコンサイズを使用(標準の75%)
75
  - フォントサイズを10%小さく設定
76
  - テキスト量が多い場合は自動的に複数列に分割表示
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  """
78
 
79
  # システムプロンプト(強化版)
@@ -137,6 +196,8 @@ def generate_html_from_text(text, temperature=1.0, layout_type="standard"):
137
  - 横幅は100%
138
  - 重要な要素は中央寄り、補足情報は周辺部に配置
139
 
 
 
140
  ## レイアウト崩れ防止のための追加設定
141
  - テキストが重ならないようにカードやセクション間に十分なマージンを設定(最低25px)
142
  - テキスト量に応じて自動的に要素の高さが伸びるフレックスレイアウトを採用
@@ -305,66 +366,191 @@ document.addEventListener('DOMContentLoaded', function() {{
305
 
306
  # HTMLを後処理してレイアウト崩れを防止する関数
307
  def enhance_html_for_layout(html_code):
308
- """HTMLを後処理してレイアウト崩れを防止するための調整を行う"""
309
  try:
310
- # テキスト重なり防止のためのスタイルが含まれているか確認
311
- if "<style>" in html_code and ".card-content" not in html_code:
312
- # スタイルタグを見つけてレイアウト崩れ防止用のCSSを追加
 
 
313
  style_pos = html_code.find("</style>")
314
  if style_pos != -1:
315
- # レイアウト崩れ防止用のCSS
316
- layout_css = """
317
- /* レイアウト崩れ防止用スタイル */
 
 
 
 
318
  .card, .section, .info-box {
319
- overflow: hidden;
320
- display: flex;
321
- flex-direction: column;
322
- margin-bottom: 1.5rem !important;
323
- min-height: fit-content;
324
- padding: 1rem !important;
 
 
 
 
 
325
  }
326
- .card-content {
327
- flex: 1;
328
- display: flex;
329
- flex-direction: column;
 
 
330
  }
331
- .card-title {
332
- font-weight: bold;
333
- margin-bottom: 0.75rem !important;
334
- line-height: 1.4;
 
 
335
  }
336
- .card-text {
337
- line-height: 1.6;
338
- margin-bottom: 0.5rem !important;
 
 
 
 
339
  }
340
- .info-item {
341
- margin-bottom: 0.75rem !important;
342
- line-height: 1.5;
 
 
343
  }
344
- li {
345
- margin-bottom: 0.5rem !important;
346
- line-height: 1.5;
 
347
  }
348
- p {
349
- margin-bottom: 0.75rem !important;
350
- line-height: 1.5;
 
 
 
 
 
 
 
 
 
351
  }
352
  """
353
  # スタイルタグの閉じ直前に挿入
354
- html_code = html_code[:style_pos] + layout_css + html_code[style_pos:]
355
 
356
- # テキスト自動調整用のスクリプトが含まれていなければ追加
357
- if "</body>" in html_code and "document.addEventListener('DOMContentLoaded'" not in html_code:
358
- # ボディタグの閉じ直前にスクリプトを追加
359
- body_end_pos = html_code.find("</body>")
360
- if body_end_pos != -1:
361
- # テキスト自動調整用のスクリプト
362
- auto_adjust_script = """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  <script>
364
- document.addEventListener('DOMContentLoaded', function() {
365
- // カード内のテキスト量に基づいてフォントサイズを調整
366
- const cards = document.querySelectorAll('.card, .section, .info-box');
367
- cards.forEach(card => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  const cardContent = card.querySelector('.card-content') || card;
369
  const textLength = cardContent.textContent.length;
370
 
@@ -383,14 +569,26 @@ document.addEventListener('DOMContentLoaded', function() {
383
  el.style.lineHeight = '1.5';
384
  });
385
  });
386
- });
 
 
 
 
 
 
 
 
 
387
  </script>
388
  """
389
- # ボディタグの閉じ直前に挿入
390
- html_code = html_code[:body_end_pos] + auto_adjust_script + html_code[body_end_pos:]
391
 
392
- # カード要素にクラス追加
393
- html_code = re.sub(r'<div class="([^"]*)"([^>]*)>', lambda m: f'<div class="{m.group(1)} card"{m.group(2)}>', html_code)
 
 
 
 
394
 
395
  return html_code
396
  except Exception as e:
@@ -512,8 +710,8 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float = 6.0
512
  )
513
  logger.info("Body element found. Waiting for potential resource loading...")
514
 
515
- # リソース読み込みの待機時間(増加:58秒)
516
- time.sleep(8) # 十分な待機時間
517
 
518
  # 5) Hide scrollbars via CSS
519
  try:
@@ -592,8 +790,8 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float = 6.0
592
  driver.set_window_size(adjusted_width, adjusted_height)
593
  logger.info("Waiting for layout stabilization after resize...")
594
 
595
- # レイアウト安定化のための待機(増加:46秒)
596
- time.sleep(6) # 統一した待機時間
597
 
598
  # 外部リソースの読み込み状態を確認
599
  try:
@@ -615,10 +813,49 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float = 6.0
615
 
616
  # レイアウト崩れ修正のためのJavaScriptを実行
617
  try:
618
- fix_layout_script = """
619
- // カード内のテキスト量に基づいてフォントサイズを調整
620
- const cards = document.querySelectorAll('.card, .section, .info-box');
621
- cards.forEach(card => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
622
  const cardContent = card.querySelector('.card-content') || card;
623
  const textLength = cardContent.textContent.length;
624
 
@@ -637,12 +874,16 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float = 6.0
637
  el.style.lineHeight = '1.5';
638
  });
639
  });
 
 
 
640
  """
641
- driver.execute_script(fix_layout_script)
642
- logger.info("Executed layout fix JavaScript")
643
 
644
- # 追加の待機時間
645
- time.sleep(1)
 
 
 
646
  except Exception as e:
647
  logger.warning(f"Failed to execute layout fix script: {e}")
648
 
@@ -915,9 +1156,10 @@ with gr.Blocks(title="Full Page Screenshot (テキスト変換対応)", theme=gr
915
  gemini_model = os.environ.get("GEMINI_MODEL", "gemini-1.5-pro")
916
  gr.Markdown(f"""
917
  ## 更新情報
918
- - テキスト重なり自動修正機能を追加
919
  - レイアウトタイプ選択機能を追加(テキストモード時)
920
  - フォントサイズ自動調整機能を追加
 
921
 
922
  ## APIエンドポイント
923
  - `/api/screenshot` - HTMLコードからスクリーンショットを生成
 
74
  - 小さめのアイコンサイズを使用(標準の75%)
75
  - フォントサイズを10%小さく設定
76
  - テキスト量が多い場合は自動的に複数列に分割表示
77
+ """
78
+
79
+ # レイアウト崩れ防止のための追加指示
80
+ layout_improvements = """
81
+ ## 重要なレイアウト指示(必ず守ってください)
82
+ - カード要素は必ずdisplay: gridまたはflexboxで配置してください
83
+ - カードの配置は絶対位置(position: absolute)を使わず、フロー配置を使ってください
84
+ - 各カードには以下のスタイルを必ず適用してください:
85
+ ```css
86
+ .card {
87
+ position: relative;
88
+ clear: both;
89
+ display: flex;
90
+ flex-direction: column;
91
+ margin: 1.5rem 0;
92
+ padding: 1.2rem;
93
+ height: auto;
94
+ overflow: visible;
95
+ box-sizing: border-box;
96
+ }
97
+ ```
98
+
99
+ - 兄弟要素間のマージンは必ず以下のように設定してください:
100
+ ```css
101
+ .card + .card,
102
+ .section + .section,
103
+ .info-box + .info-box,
104
+ .row + .row {
105
+ margin-top: 2rem;
106
+ }
107
+ ```
108
+
109
+ - コンテナの高さは自動的に調整されるようにしてください:
110
+ ```css
111
+ .container, .row, .column {
112
+ height: auto;
113
+ overflow: hidden;
114
+ display: flex;
115
+ flex-direction: column;
116
+ }
117
+ ```
118
+
119
+ - グリッドレイアウトを使用する場合は明示的な行の高さを設定してください:
120
+ ```css
121
+ .grid {
122
+ display: grid;
123
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
124
+ grid-gap: 2rem;
125
+ grid-auto-rows: minmax(min-content, auto);
126
+ }
127
+ ```
128
+
129
+ - すべてのテキスト要素に余白を設定してください:
130
+ ```css
131
+ p, h1, h2, h3, h4, h5, h6, li {
132
+ margin-bottom: 1rem;
133
+ line-height: 1.6;
134
+ }
135
+ ```
136
  """
137
 
138
  # システムプロンプト(強化版)
 
196
  - 横幅は100%
197
  - 重要な要素は中央寄り、補足情報は周辺部に配置
198
 
199
+ {layout_improvements}
200
+
201
  ## レイアウト崩れ防止のための追加設定
202
  - テキストが重ならないようにカードやセクション間に十分なマージンを設定(最低25px)
203
  - テキスト量に応じて自動的に要素の高さが伸びるフレックスレイアウトを採用
 
366
 
367
  # HTMLを後処理してレイアウト崩れを防止する関数
368
  def enhance_html_for_layout(html_code):
369
+ """HTMLを後処理してレイアウト崩れを防止するための調整を行う(強化版)"""
370
  try:
371
+ # 基本的なスタイルとスクリプトが含まれているか確認
372
+ base_styles_needed = True
373
+ base_scripts_needed = True
374
+
375
+ if "<style>" in html_code:
376
  style_pos = html_code.find("</style>")
377
  if style_pos != -1:
378
+ # カード要素のスタイルが含まれているか確認
379
+ if ".card" in html_code[:style_pos] and "flex-direction: column" in html_code[:style_pos]:
380
+ base_styles_needed = False
381
+
382
+ # レイアウト崩れ防止用の強化CSSを追加
383
+ enhanced_css = """
384
+ /* --- レイアウト崩れ防止強化スタイル --- */
385
  .card, .section, .info-box {
386
+ position: relative !important;
387
+ display: flex !important;
388
+ flex-direction: column !important;
389
+ margin: 1.5rem 0 !important;
390
+ padding: 1.2rem !important;
391
+ height: auto !important;
392
+ min-height: fit-content !important;
393
+ overflow: visible !important;
394
+ box-sizing: border-box !important;
395
+ z-index: 1 !important;
396
+ clear: both !important;
397
  }
398
+
399
+ /* フローティング要素のクリア */
400
+ .clearfix::after {
401
+ content: "" !important;
402
+ display: table !important;
403
+ clear: both !important;
404
  }
405
+
406
+ /* コンテナ要素の高さ自動調整 */
407
+ .container, .row, .column {
408
+ height: auto !important;
409
+ overflow: hidden !important;
410
+ position: relative !important;
411
  }
412
+
413
+ /* グリッドレイア���トの調整 */
414
+ .grid {
415
+ display: grid !important;
416
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important;
417
+ grid-gap: 2rem !important;
418
+ grid-auto-rows: minmax(min-content, auto) !important;
419
  }
420
+
421
+ /* マージンとパディングの強制 */
422
+ p, h1, h2, h3, h4, h5, h6, li {
423
+ margin-bottom: 1rem !important;
424
+ line-height: 1.6 !important;
425
  }
426
+
427
+ /* 重なり解消のための特別なスタイル */
428
+ body {
429
+ overflow-x: hidden !important;
430
  }
431
+
432
+ .card + .card, .section + .section, .info-box + .info-box {
433
+ margin-top: 2rem !important;
434
+ }
435
+
436
+ /* モバイル表示の改善 */
437
+ @media (max-width: 768px) {
438
+ .card, .section, .info-box {
439
+ width: 100% !important;
440
+ margin-left: 0 !important;
441
+ margin-right: 0 !important;
442
+ }
443
  }
444
  """
445
  # スタイルタグの閉じ直前に挿入
446
+ html_code = html_code[:style_pos] + enhanced_css + html_code[style_pos:]
447
 
448
+ # スタイルが存在しない場合は新たに追加
449
+ if base_styles_needed and "<style>" not in html_code:
450
+ head_end_pos = html_code.find("</head>")
451
+ if head_end_pos != -1:
452
+ base_styles = """
453
+ <style>
454
+ /* ベーススタイル - レイアウト崩れ防止 */
455
+ .card, .section, .info-box {
456
+ position: relative !important;
457
+ display: flex !important;
458
+ flex-direction: column !important;
459
+ margin: 1.5rem 0 !important;
460
+ padding: 1.2rem !important;
461
+ height: auto !important;
462
+ min-height: fit-content !important;
463
+ overflow: visible !important;
464
+ box-sizing: border-box !important;
465
+ z-index: 1 !important;
466
+ clear: both !important;
467
+ }
468
+
469
+ .card-content {
470
+ flex: 1 !important;
471
+ display: flex !important;
472
+ flex-direction: column !important;
473
+ }
474
+
475
+ .container, .row, .column {
476
+ height: auto !important;
477
+ overflow: hidden !important;
478
+ position: relative !important;
479
+ }
480
+
481
+ p, h1, h2, h3, h4, h5, h6, li {
482
+ margin-bottom: 1rem !important;
483
+ line-height: 1.6 !important;
484
+ }
485
+
486
+ /* 重なり解消のための特別なスタイル */
487
+ body {
488
+ overflow-x: hidden !important;
489
+ }
490
+
491
+ .card + .card, .section + .section, .info-box + .info-box {
492
+ margin-top: 2rem !important;
493
+ }
494
+ </style>
495
+ """
496
+ html_code = html_code[:head_end_pos] + base_styles + html_code[head_end_pos:]
497
+
498
+ # 自動レイアウト修正用のスクリプトを強化
499
+ if "</body>" in html_code:
500
+ has_stabilize_script = "stabilizeLayout" in html_code
501
+
502
+ if not has_stabilize_script:
503
+ body_end_pos = html_code.find("</body>")
504
+ if body_end_pos != -1:
505
+ enhanced_script = """
506
  <script>
507
+ // レイアウト安定化のための強化スクリプト
508
+ function stabilizeLayout() {
509
+ // カードの重なりを解消
510
+ document.querySelectorAll('.card, .section, .info-box').forEach(card => {
511
+ // 位置を相対指定に強制
512
+ card.style.position = 'relative';
513
+
514
+ // z-indexをカード間で競合しないよう設定
515
+ card.style.zIndex = '1';
516
+
517
+ // マージンを強制的に設定
518
+ card.style.marginBottom = '2rem';
519
+ card.style.marginTop = '1rem';
520
+
521
+ // 浮動要素のクリア
522
+ let clearDiv = document.createElement('div');
523
+ clearDiv.style.clear = 'both';
524
+ clearDiv.style.height = '1px';
525
+ card.parentNode.insertBefore(clearDiv, card.nextSibling);
526
+
527
+ // クリアフィックスクラスを追加
528
+ card.classList.add('clearfix');
529
+ });
530
+
531
+ // 親要素の高さを適切に設定
532
+ document.querySelectorAll('.row, .container, .column').forEach(container => {
533
+ container.style.overflow = 'hidden';
534
+ container.style.height = 'auto';
535
+ container.classList.add('clearfix');
536
+
537
+ // 子要素の合計高さを取得して設定
538
+ let totalHeight = 0;
539
+ Array.from(container.children).forEach(child => {
540
+ if (child.offsetHeight) {
541
+ totalHeight += child.offsetHeight +
542
+ parseInt(getComputedStyle(child).marginTop || 0) +
543
+ parseInt(getComputedStyle(child).marginBottom || 0);
544
+ }
545
+ });
546
+
547
+ if (totalHeight > 0) {
548
+ container.style.minHeight = (totalHeight + 50) + 'px';
549
+ }
550
+ });
551
+
552
+ // テキスト量に基づいてフォントサイズを調整
553
+ document.querySelectorAll('.card, .section, .info-box').forEach(card => {
554
  const cardContent = card.querySelector('.card-content') || card;
555
  const textLength = cardContent.textContent.length;
556
 
 
569
  el.style.lineHeight = '1.5';
570
  });
571
  });
572
+ }
573
+
574
+ // DOMContentLoadedイベントで実行
575
+ document.addEventListener('DOMContentLoaded', stabilizeLayout);
576
+
577
+ // 安全のためにウィンドウロード時にも実行
578
+ window.addEventListener('load', stabilizeLayout);
579
+
580
+ // 1秒後に再度実行して安定化を確実にする
581
+ setTimeout(stabilizeLayout, 1000);
582
  </script>
583
  """
584
+ html_code = html_code[:body_end_pos] + enhanced_script + html_code[body_end_pos:]
 
585
 
586
+ # カードコンテナのクラス追加
587
+ html_code = re.sub(r'<div class="([^"]*)"([^>]*)>', lambda m: f'<div class="{m.group(1)} card clearfix"{m.group(2)}>', html_code)
588
+
589
+ # ボディタグにクラス追加
590
+ if "<body" in html_code and "clearfix" not in html_code:
591
+ html_code = html_code.replace("<body", '<body class="clearfix"')
592
 
593
  return html_code
594
  except Exception as e:
 
710
  )
711
  logger.info("Body element found. Waiting for potential resource loading...")
712
 
713
+ # リソース読み込みの待機時間(増加:810秒)
714
+ time.sleep(10) # 十分な待機時間
715
 
716
  # 5) Hide scrollbars via CSS
717
  try:
 
790
  driver.set_window_size(adjusted_width, adjusted_height)
791
  logger.info("Waiting for layout stabilization after resize...")
792
 
793
+ # レイアウト安定化のための待機(増加:68秒)
794
+ time.sleep(8) # 統一した待機時間
795
 
796
  # 外部リソースの読み込み状態を確認
797
  try:
 
813
 
814
  # レイアウト崩れ修正のためのJavaScriptを実行
815
  try:
816
+ # レイアウト安定化のための強化JavaScriptを実行
817
+ stabilize_script = """
818
+ // カードの重なりを解消するための修正
819
+ document.querySelectorAll('.card, .section, .info-box').forEach(card => {
820
+ // 位置を相対指定に強制
821
+ card.style.position = 'relative';
822
+
823
+ // z-indexをカード間で競合しないよう設定
824
+ card.style.zIndex = '1';
825
+
826
+ // マージンを強制的に設定
827
+ card.style.marginBottom = '2rem';
828
+ card.style.marginTop = '1rem';
829
+
830
+ // 浮動要素のクリア
831
+ let clearDiv = document.createElement('div');
832
+ clearDiv.style.clear = 'both';
833
+ clearDiv.style.height = '1px';
834
+ card.parentNode.insertBefore(clearDiv, card.nextSibling);
835
+ });
836
+
837
+ // 親要素の高さを適切に設定
838
+ document.querySelectorAll('.row, .container, .column').forEach(container => {
839
+ container.style.overflow = 'hidden';
840
+ container.style.height = 'auto';
841
+
842
+ // 子要素の合計高さを取得して設定
843
+ let totalHeight = 0;
844
+ Array.from(container.children).forEach(child => {
845
+ if (child.offsetHeight) {
846
+ totalHeight += child.offsetHeight +
847
+ parseInt(getComputedStyle(child).marginTop || 0) +
848
+ parseInt(getComputedStyle(child).marginBottom || 0);
849
+ }
850
+ });
851
+
852
+ if (totalHeight > 0) {
853
+ container.style.minHeight = (totalHeight + 50) + 'px';
854
+ }
855
+ });
856
+
857
+ // テキスト量に基づいてフォントサイズを調整
858
+ document.querySelectorAll('.card, .section, .info-box').forEach(card => {
859
  const cardContent = card.querySelector('.card-content') || card;
860
  const textLength = cardContent.textContent.length;
861
 
 
874
  el.style.lineHeight = '1.5';
875
  });
876
  });
877
+
878
+ // 完了通知
879
+ return "Layout stabilization completed";
880
  """
 
 
881
 
882
+ stabilize_result = driver.execute_script(stabilize_script)
883
+ logger.info(f"Layout stabilization: {stabilize_result}")
884
+
885
+ # 安定化後の追加待機
886
+ time.sleep(2)
887
  except Exception as e:
888
  logger.warning(f"Failed to execute layout fix script: {e}")
889
 
 
1156
  gemini_model = os.environ.get("GEMINI_MODEL", "gemini-1.5-pro")
1157
  gr.Markdown(f"""
1158
  ## 更新情報
1159
+ - テキスト重なり自動修正機能を強化
1160
  - レイアウトタイプ選択機能を追加(テキストモード時)
1161
  - フォントサイズ自動調整機能を追加
1162
+ - レンダリング待機時間の最適化
1163
 
1164
  ## APIエンドポイント
1165
  - `/api/screenshot` - HTMLコードからスクリーンショットを生成