ponkotsu-md-editor 0.1.10 → 0.1.11

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: 9b28859d9545a2b22a23f784e378112610c1d01df952201e77a5fb165f725fb0
4
- data.tar.gz: 6142db919d87d110f5037c612d9f23fb2b502cf852fead4017dc7a0e178b1258
3
+ metadata.gz: f368e5ac8edd2f609cb8d806e1a9396468883cd9455ce681ede8f1e61d33278a
4
+ data.tar.gz: 3cf05435af1e6ddac2d45fffa72158cabf61f94387a1e67d9d0010098358ab12
5
5
  SHA512:
6
- metadata.gz: 7eed329ecb08aa119dbecc4a166aebfaf55412e31d71e0788d7895db7e97e984906dc0e25ff6aa17cadc7cf14b9e18d74b3ba16a13a19d18da6637d57fe72688
7
- data.tar.gz: 7803dbff76c6bbc05d9470a519976f30490b116b75c88d2164218b397d6c356ba79b223f6f265b51a32c1538756c4e3f04770abbccab137f7af0205b88efc30c
6
+ metadata.gz: 06d90cf57121c150bba6cedfb5ad0e5077588177b0ed53dcccd9c00263a125386c90b2ad854fcdf952e0ea68bf456efaef232bef2ee0842249d046913eb970c6
7
+ data.tar.gz: 5d08cdf6a4b4226985a78b54eb12c3707a1c7c0dc2520559afeb9a3b06af5a2fadbb917888c4c1d02782a5c52d02c5a09f05f6b30ef6b5cc30abf49fb0a5d0f8
@@ -27,10 +27,6 @@
27
27
  const textarea = getElement('.markdown-textarea');
28
28
  const previewContainer = getElement('#markdownPreview');
29
29
  const previewToggle = getElement('#previewToggle');
30
- const titleField = getElement('#article_title');
31
- const slugField = getElement('#article_slug');
32
- const generateBtn = getElement('#generateSlugBtn');
33
- const slugPreview = getElement('#slugPreview');
34
30
 
35
31
  let isPreviewMode = false;
36
32
 
@@ -73,7 +69,7 @@
73
69
  };
74
70
 
75
71
  window.insertCode = function() {
76
- const textarea = document.getElementById('article_content');
72
+ const textarea = document.getElementById('editor_content');
77
73
  const selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
78
74
 
79
75
  if (selectedText.includes('\n')) {
@@ -648,16 +644,6 @@
648
644
  }
649
645
  };
650
646
 
651
- // デバッグ用:サニタイズテスト
652
- window.testSanitization = function() {
653
- const testInput = `<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ニーアでも聞きながら作業しますかね。<a href="https://t.co/Ac9X8lEaZL">https://t.co/Ac9X8lEaZL</a></p>&mdash; ボイラー (@dhq_boiler) <a href="https://twitter.com/dhq_boiler/status/1942584009550409780?ref_src=twsrc%5Etfw">July 8, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>`;
654
-
655
- const result = convertMarkdownToHtml(testInput);
656
- console.log('Original:', testInput);
657
- console.log('Converted:', result);
658
- return result;
659
- };
660
-
661
647
  // Twitter埋め込み用のヘルパー関数
662
648
  window.insertTwitterEmbed = function() {
663
649
  const tweetUrl = prompt('TwitterのツイートURLを入力してください:');
@@ -669,7 +655,7 @@
669
655
  return;
670
656
  }
671
657
 
672
- const textarea = document.getElementById('article_content');
658
+ const textarea = document.getElementById('editor_content');
673
659
  if (!textarea) return;
674
660
 
675
661
  // 簡単なTwitter埋め込みコードのテンプレート
@@ -686,6 +672,31 @@
686
672
  alert('基本的なTwitter埋め込みを挿入しました。\n\n完全な埋め込みには、Twitter公式から生成されたコードを使用してください。');
687
673
  };
688
674
 
675
+ // テキストエリアのカーソル位置にテキストを挿入
676
+ window.insertTextAtCursor = function(textarea, text) {
677
+ if (!textarea || !text) return;
678
+
679
+ const start = textarea.selectionStart;
680
+ const end = textarea.selectionEnd;
681
+ const currentValue = textarea.value;
682
+
683
+ // 挿入位置の前後に改行を追加(必要に応じて)
684
+ let insertText = text;
685
+ if (start > 0 && currentValue[start - 1] !== '\n') {
686
+ insertText = '\n' + insertText;
687
+ }
688
+ if (end < currentValue.length && currentValue[end] !== '\n') {
689
+ insertText = insertText + '\n';
690
+ }
691
+
692
+ textarea.value = currentValue.substring(0, start) + insertText + currentValue.substring(end);
693
+ textarea.focus();
694
+ textarea.selectionStart = textarea.selectionEnd = start + insertText.length;
695
+
696
+ // Railsのフォームバリデーション用にchangeイベントを発火
697
+ textarea.dispatchEvent(new Event('change', { bubbles: true }));
698
+ }
699
+
689
700
  // 遅延実行のためのデバウンス関数
690
701
  function debounce(func, wait) {
691
702
  let timeout;
@@ -738,115 +749,9 @@
738
749
  });
739
750
  }
740
751
 
741
- // フォームバリデーション
742
- const form = getElement('.article-form');
743
- if (form) {
744
- form.addEventListener('submit', function(e) {
745
- const title = titleField && titleField.value.trim();
746
- const content = textarea && textarea.value.trim();
747
-
748
- if (!title) {
749
- e.preventDefault();
750
- alert('タイトルを入力してください');
751
- if (titleField) {
752
- titleField.focus();
753
- titleField.scrollIntoView({ behavior: 'smooth' });
754
- }
755
- return false;
756
- }
757
-
758
- if (!content) {
759
- e.preventDefault();
760
- alert('本文を入力してください');
761
- if (textarea) {
762
- textarea.focus();
763
- textarea.scrollIntoView({ behavior: 'smooth' });
764
- }
765
- return false;
766
- }
767
-
768
- // スラッグが空の場合は最後の努力で生成
769
- if (slugField && !slugField.value.trim() && title) {
770
- e.preventDefault();
771
-
772
- generateHighQualitySlug(title).then(slug => {
773
- if (slug) {
774
- slugField.value = slug;
775
- form.submit(); // 再送信
776
- } else {
777
- alert('スラッグの生成に失敗しました。手動で入力してください。');
778
- slugField.focus();
779
- }
780
- }).catch(error => {
781
- console.error('Final slug generation failed:', error);
782
- alert('スラッグの生成でエラーが発生しました。手動で入力してください。');
783
- slugField.focus();
784
- });
785
-
786
- return false;
787
- }
788
-
789
- // スラッグの形式チェック
790
- if (slugField && slugField.value.trim()) {
791
- const slug = slugField.value.trim();
792
- if (!/^[a-z0-9\-]+$/.test(slug)) {
793
- e.preventDefault();
794
- alert('スラッグは英小文字、数字、ハイフンのみ使用できます');
795
- slugField.focus();
796
- slugField.select();
797
- return false;
798
- }
799
- }
800
- });
801
- }
802
-
803
- // リアルタイムバリデーション
804
- if (slugField) {
805
- slugField.addEventListener('blur', function() {
806
- const slug = this.value.trim();
807
- if (slug && !/^[a-z0-9\-]+$/.test(slug)) {
808
- this.classList.add('is-invalid');
809
-
810
- // エラーメッセージを表示
811
- let errorDiv = this.parentNode.querySelector('.invalid-feedback');
812
- if (!errorDiv) {
813
- errorDiv = document.createElement('div');
814
- errorDiv.className = 'invalid-feedback';
815
- this.parentNode.appendChild(errorDiv);
816
- }
817
- errorDiv.textContent = '英小文字、数字、ハイフンのみ使用できます';
818
- } else {
819
- this.classList.remove('is-invalid');
820
- const errorDiv = this.parentNode.querySelector('.invalid-feedback');
821
- if (errorDiv) {
822
- errorDiv.remove();
823
- }
824
- }
825
- });
826
- }
827
-
828
752
  console.log('ponkotsu Markdown editor initialized successfully');
829
753
  });
830
754
 
831
- // ページ離脱確認
832
- window.addEventListener('beforeunload', function(e) {
833
- try {
834
- const textarea = getElement('.markdown-textarea');
835
- const titleField = getElement('#article_title');
836
-
837
- const hasContent = (textarea && textarea.value.trim()) ||
838
- (titleField && titleField.value.trim());
839
-
840
- if (hasContent) {
841
- const message = '編集中の内容が失われますがよろしいですか?';
842
- e.returnValue = message;
843
- return message;
844
- }
845
- } catch (error) {
846
- console.error('Beforeunload error:', error);
847
- }
848
- });
849
-
850
755
  // エラーハンドリングの強化
851
756
  window.addEventListener('error', function(e) {
852
757
  if (e.message.includes('markdown') || e.message.includes('slug')) {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PonkotsuMdEditor
4
- VERSION = "0.1.10"
4
+ VERSION = "0.1.11"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ponkotsu-md-editor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - dhq_boiler