diff --git a/builder/commons.py b/builder/commons.py
index e3b2870..39450a5 100644
--- a/builder/commons.py
+++ b/builder/commons.py
@@ -69,6 +69,16 @@ def dialogue_from_info(act: Action, lang: LangType) -> str:
     return "「{}」".format(infos_of(act).replace('/', '、')) if lang == LangType.JPN else ' "{}" '.format(infos_of(act).replace('/', ', '))
 
 
+def double_comma_chopped(target: str, lang: LangType) -> str:
+    assert_isstr(target)
+    assert_isclass(lang, LangType)
+
+    if lang is LangType.JPN:
+        return re.sub(r'([、。]){2}', r'\1', target)
+    else:
+        return re.sub(r'([,\.]){2}', r'\1', target)
+
+
 def extraend_chopped(target: str, lang: LangType) -> str:
     assert_isstr(target)
     assert_isclass(lang, LangType)
@@ -84,7 +94,7 @@ def extraspace_chopped(target: str, lang: LangType) -> str:
     assert_isclass(lang, LangType)
 
     if lang is LangType.JPN:
-        return re.sub(r'。[　、](.)', r'。\1', target)
+        return re.sub(r'([。」])[　、](.)', r'\1\2', target)
     else:
         return re.sub(r' +', r' ', target)
 
diff --git a/builder/tools.py b/builder/tools.py
index ec01600..289d08c 100644
--- a/builder/tools.py
+++ b/builder/tools.py
@@ -8,7 +8,8 @@ import re
 from .sbutils import assert_isclass, assert_isbool, assert_isint, assert_isstr
 from .action import Action, ActionGroup, TagAction
 from .commons import behavior_with_np_of, descriptions_of_if, dialogue_from_description_if, dialogue_from_info
-from .commons import extraspace_chopped, extraend_chopped, infos_of, object_names_of, sentence_from, subject_name_of
+from .commons import double_comma_chopped, extraspace_chopped, extraend_chopped
+from .commons import infos_of, object_names_of, sentence_from, subject_name_of
 from .enums import ActType, GroupType, TagType, LangType
 from .subject import _BaseSubject
 from .person import Person
@@ -285,6 +286,18 @@ def _desc_excepted_symbols(target: str) -> str:
 
     return re.sub(r'　|\s|\n|\r', '', target)
 
+
+def _extra_chopped(target: str, lang: LangType) -> str:
+    assert_isstr(target)
+    assert_isclass(lang, LangType)
+
+    return double_comma_chopped(
+            extraend_chopped(
+                extraspace_chopped(target, lang),
+                lang),
+            lang)
+
+
 def _flag_info_if(act: Action) -> str:
     assert_isclass(act, Action)
 
@@ -412,9 +425,9 @@ def _story_converted_as_description_in_group(group: ActionGroup, group_type: Gro
         else:
             val = _description_of_by_type(a, group.lang, group.group_type, level, pri_filter, is_debug)
             if val:
-                tmp.append(extraend_chopped(extraspace_chopped(val, group.lang), group.lang))
+                tmp.append(_extra_chopped(val, group.lang))
     if group_type is GroupType.COMBI:
-        return [extraend_chopped(extraspace_chopped("".join(tmp), group.lang), group.lang),]
+        return [_extra_chopped("".join(tmp), group.lang),]
     else:
         return tmp
 

Need to fix: kakko space bug
”」　”になる
===

**Description**
かぎかっこの後については考慮されていなかったようで、combineしてしまうとそこが空白が空いてしまう。

diff --git a/tests/test_commons.py b/tests/test_commons.py
index d31cac1..7251069 100644
--- a/tests/test_commons.py
+++ b/tests/test_commons.py
@@ -128,6 +128,18 @@ class PublicMethodsTest(unittest.TestCase):
             with self.subTest(act=act, lng=lng, expected=expected):
                 self.assertEqual(commons.dialogue_from_info(act, lng), expected)
 
+    def test_double_comma_chopped(self):
+        data = [
+                ("　これを。。ただしく。。", LangType.JPN,
+                    "　これを。ただしく。"),
+                (" This is a pen.. the pen. ", LangType.ENG,
+                    " This is a pen. the pen. "),
+                ]
+
+        for v, lng, expected in data:
+            with self.subTest(v=v, lng=lng, expected=expected):
+                self.assertEqual(commons.double_comma_chopped(v, lng), expected)
+
     def test_extraspace_chopped(self):
         data = [
                 ("　これを。　ただしくする。", LangType.JPN,
@@ -136,6 +148,8 @@ class PublicMethodsTest(unittest.TestCase):
                     " This is a pen. the pen. "),
                 ("　これを。、ただしくして。", LangType.JPN,
                     "　これを。ただしくして。"),
+                ("「これを」　正しくする。", LangType.JPN,
+                    "「これを」正しくする。"),
                 ]
 
         for v, lng, expected in data:

pip install -e .
parse_log_pytest
pytest
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pytest @ file:///croot/pytest_1738938843180/work
-e git+https://github.com/nagisc007/storybuilder.git@7f364a8a36eee01df5d51157cd4b5c5eefaf34e5#egg=StoryBuilder
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work

name: storybuilder
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
prefix: /opt/conda/envs/storybuilder

tests/test_commons.py::PublicMethodsTest::test_double_comma_chopped tests/test_commons.py::PublicMethodsTest::test_extraspace_chopped
tests/test_commons.py::PublicMethodsTest::test_behavior_with_np_of tests/test_commons.py::PublicMethodsTest::test_comma_of tests/test_commons.py::PublicMethodsTest::test_description_of tests/test_commons.py::PublicMethodsTest::test_description_of_if tests/test_commons.py::PublicMethodsTest::test_dialogue_from_description tests/test_commons.py::PublicMethodsTest::test_dialogue_from_description_if tests/test_commons.py::PublicMethodsTest::test_dialogue_from_info tests/test_commons.py::PublicMethodsTest::test_infos_of tests/test_commons.py::PublicMethodsTest::test_object_names_of tests/test_commons.py::PublicMethodsTest::test_object_names_of_without_something tests/test_commons.py::PublicMethodsTest::test_objects_all_from tests/test_commons.py::PublicMethodsTest::test_objects_from tests/test_commons.py::PublicMethodsTest::test_objects_from_action_without_something tests/test_commons.py::PublicMethodsTest::test_objects_from_without_something tests/test_commons.py::PublicMethodsTest::test_sentence_from tests/test_commons.py::PublicMethodsTest::test_something_name_if tests/test_commons.py::PublicMethodsTest::test_subject_name_of tests/test_commons.py::PrivateMethodsTest::test_endpoint_replaced_if_with_comma tests/test_commons.py::PrivateMethodsTest::test_space_replaced_if_with_symbol
builder/tools.py builder/commons.py
builder/tools.py builder/commons.py