diff --git a/src/openstep_plist/__main__.py b/src/openstep_plist/__main__.py
index 673128b..9165225 100755
--- a/src/openstep_plist/__main__.py
+++ b/src/openstep_plist/__main__.py
@@ -37,6 +37,9 @@ def main(args=None):
         "-j", "--json", help="use json to serialize", action="store_true", default=False
     )
     parser.add_argument("-i", "--indent", help="indentation level", type=int, default=2)
+    parser.add_argument(
+        "--no-escape-newlines", dest="escape_newlines", action="store_false"
+    )
     args = parser.parse_args(args)
 
     if not args.glyphs:
@@ -58,7 +61,11 @@ def main(args=None):
         if args.glyphs:
             from glyphsLib.writer import dump
         else:
-            dump = partial(openstep_plist.dump, indent=args.indent)
+            dump = partial(
+                openstep_plist.dump,
+                indent=args.indent,
+                escape_newlines=args.escape_newlines,
+            )
 
     with open(args.infile, "r", encoding="utf-8") as fp:
         data = parse(fp)
diff --git a/src/openstep_plist/writer.pyx b/src/openstep_plist/writer.pyx
index 46a693e..ffbb98b 100644
--- a/src/openstep_plist/writer.pyx
+++ b/src/openstep_plist/writer.pyx
@@ -117,6 +117,7 @@ cdef class Writer:
     cdef unicode indent
     cdef int current_indent_level
     cdef bint single_line_tuples
+    cdef bint escape_newlines
 
     def __cinit__(
         self,
@@ -124,10 +125,12 @@ cdef class Writer:
         int float_precision=6,
         indent=None,
         bint single_line_tuples=False,
+        bint escape_newlines=True,
     ):
         self.dest = new vector[Py_UCS4]()
         self.unicode_escape = unicode_escape
         self.float_precision = float_precision
+        self.escape_newlines = escape_newlines
 
         if indent is not None:
             if isinstance(indent, basestring):
@@ -225,14 +228,17 @@ cdef class Writer:
             unsigned long ch
             Py_ssize_t base_length = dest.size()
             Py_ssize_t new_length = 0
+            bint escape_newlines = self.escape_newlines
 
         while curr < end:
             ch = curr[0]
-            if ch == c'\t' or ch == c' ':
+            if ch == c'\t' or ch == c' ' or (ch == c'\n' and not escape_newlines):
                 new_length += 1
             elif (
-                ch == c'\n' or ch == c'\\' or ch == c'"' or ch == c'\a'
+                ch == c'\\' or ch == c'"' or ch == c'\a'
                 or ch == c'\b' or ch == c'\v' or ch == c'\f' or ch == c'\r'
+            ) or (
+                ch == c'\n' and escape_newlines
             ):
                 new_length += 2
             else:
@@ -258,10 +264,10 @@ cdef class Writer:
         curr = s
         while curr < end:
             ch = curr[0]
-            if ch == c'\t' or ch == c' ':
+            if ch == c'\t' or ch == c' ' or (ch == c'\n' and not escape_newlines):
                 ptr[0] = ch
                 ptr += 1
-            elif ch == c'\n':
+            elif ch == c'\n' and escape_newlines:
                 ptr[0] = c'\\'; ptr[1] = c'n'; ptr += 2
             elif ch == c'\a':
                 ptr[0] = c'\\'; ptr[1] = c'a'; ptr += 2
@@ -584,24 +590,26 @@ cdef class Writer:
 
 
 def dumps(obj, bint unicode_escape=True, int float_precision=6, indent=None,
-          single_line_tuples=False):
+          bint single_line_tuples=False, bint escape_newlines=True):
     w = Writer(
         unicode_escape=unicode_escape,
         float_precision=float_precision,
         indent=indent,
         single_line_tuples=single_line_tuples,
+        escape_newlines=escape_newlines,
     )
     w.write(obj)
     return w.getvalue()
 
 
 def dump(obj, fp, bint unicode_escape=True, int float_precision=6, indent=None,
-         single_line_tuples=False):
+         bint single_line_tuples=False, bint escape_newlines=True):
     w = Writer(
         unicode_escape=unicode_escape,
         float_precision=float_precision,
         indent=indent,
         single_line_tuples=single_line_tuples,
+        escape_newlines=escape_newlines,
     )
     w.write(obj)
     w.dump(fp)

diff --git a/tests/test_writer.py b/tests/test_writer.py
index 3197766..8306bde 100644
--- a/tests/test_writer.py
+++ b/tests/test_writer.py
@@ -4,6 +4,7 @@ import openstep_plist
 from openstep_plist.writer import Writer, string_needs_quotes
 from io import StringIO, BytesIO
 from collections import OrderedDict
+from textwrap import dedent
 import string
 import random
 import pytest
@@ -57,6 +58,11 @@ class TestWriter(object):
         w.write(string)
         assert w.getvalue() == expected
 
+    def test_quoted_string_dont_escape_newlines(self):
+        w = Writer(escape_newlines=False)
+        w.write("a\n\n\nbc")
+        assert w.getvalue() == '"a\n\n\nbc"'
+
     def test_quoted_string_no_unicode_escape(self):
         w = Writer(unicode_escape=False)
         w.write("\u0410") == 3
@@ -211,17 +217,36 @@ def test_dumps():
         '{a = 1; b = 3; "c d" = (33, 44); '
         "e = (<66676869 6C6D6E6F>, <70717273 7475767A>);}"
     )
+    assert openstep_plist.dumps(
+        {
+            "features": dedent(
+                """\
+                sub periodcentered by periodcentered.case;
+                sub bullet by bullet.case;
+                """
+            ),
+        },
+        escape_newlines=False,
+    ) == (
+        '{features = "sub periodcentered by periodcentered.case;\n'
+        'sub bullet by bullet.case;\n'
+        '";}'
+    )
 
 
 def test_dump():
-    plist = [1, b"2", {3: (4, "5", "\U0001F4A9")}]
+    plist = [1, b"2", {3: (4, "5\n6", "\U0001F4A9")}]
     fp = StringIO()
     openstep_plist.dump(plist, fp)
-    assert fp.getvalue() == '(1, <32>, {"3" = (4, "5", "\\UD83D\\UDCA9");})'
+    assert fp.getvalue() == '(1, <32>, {"3" = (4, "5\\n6", "\\UD83D\\UDCA9");})'
 
     fp = BytesIO()
     openstep_plist.dump(plist, fp, unicode_escape=False)
-    assert fp.getvalue() == b'(1, <32>, {"3" = (4, "5", "\xf0\x9f\x92\xa9");})'
+    assert fp.getvalue() == b'(1, <32>, {"3" = (4, "5\\n6", "\xf0\x9f\x92\xa9");})'
+
+    fp = BytesIO()
+    openstep_plist.dump(plist, fp, escape_newlines=False, unicode_escape=False)
+    assert fp.getvalue() == b'(1, <32>, {"3" = (4, "5\n6", "\xf0\x9f\x92\xa9");})'
 
     with pytest.raises(AttributeError):
         openstep_plist.dump(plist, object())

[writer] add option to not escape newline characters
as @arrowtype noted in
https://github.com/googlefonts/glyphsLib/issues/953#issuecomment-1789998384
tests/test_writer.py::test_string_needs_quotes[{-True]
tests/test_writer.py::TestWriter::test_simple tests/test_writer.py::TestWriter::test_None tests/test_writer.py::TestWriter::test_unquoted_string tests/test_writer.py::TestWriter::test_quoted_string[-""] tests/test_writer.py::TestWriter::test_quoted_string[\t-"\t"] tests/test_writer.py::TestWriter::test_quoted_string[\n\x07\x08\x0b\x0c\r-"\\n\\a\\b\\v\\f\\r"] tests/test_writer.py::TestWriter::test_quoted_string[\\-"\\\\"] tests/test_writer.py::TestWriter::test_quoted_string["-"\\""] tests/test_writer.py::TestWriter::test_quoted_string[\x00\x01\x02\x03\x04\x05\x06-"\\000\\001\\002\\003\\004\\005\\006"] tests/test_writer.py::TestWriter::test_quoted_string[\x0e\x0f\x10\x11\x12\x13-"\\016\\017\\020\\021\\022\\023"] tests/test_writer.py::TestWriter::test_quoted_string[\x14\x15\x16\x17\x18\x19-"\\024\\025\\026\\027\\030\\031"] tests/test_writer.py::TestWriter::test_quoted_string[\x1a\x1b\x1c\x1d\x1e\x1f\x7f-"\\032\\033\\034\\035\\036\\037\\177"] tests/test_writer.py::TestWriter::test_quoted_string[\x80\x81\x9e\x9f\xa0-"\\U0080\\U0081\\U009E\\U009F\\U00A0"] tests/test_writer.py::TestWriter::test_quoted_string[\U0001f4a9-"\\UD83D\\UDCA9"] tests/test_writer.py::TestWriter::test_quoted_string[1-"1"] tests/test_writer.py::TestWriter::test_quoted_string[1.1-"1.1"] tests/test_writer.py::TestWriter::test_quoted_string[-23-"-23"] tests/test_writer.py::TestWriter::test_quoted_string[-23yyy-"-23yyy"] tests/test_writer.py::TestWriter::test_quoted_string[--"-"] tests/test_writer.py::TestWriter::test_quoted_string[-a--"-a-"] tests/test_writer.py::TestWriter::test_quoted_string_no_unicode_escape tests/test_writer.py::TestWriter::test_int[0-0] tests/test_writer.py::TestWriter::test_int[1-1] tests/test_writer.py::TestWriter::test_int[123-123] tests/test_writer.py::TestWriter::test_int[9223372036854775807-9223372036854775807] tests/test_writer.py::TestWriter::test_int[9223372036854775808-9223372036854775808] tests/test_writer.py::TestWriter::test_float[0.0-0] tests/test_writer.py::TestWriter::test_float[1.0-1] tests/test_writer.py::TestWriter::test_float[123.456-123.456] tests/test_writer.py::TestWriter::test_float[0.01-0.01] tests/test_writer.py::TestWriter::test_float[0.001-0.001] tests/test_writer.py::TestWriter::test_float[0.0001-0.0001] tests/test_writer.py::TestWriter::test_float[1e-05-0.00001] tests/test_writer.py::TestWriter::test_float[1e-06-0.000001] tests/test_writer.py::TestWriter::test_float[1e-07-0] tests/test_writer.py::TestWriter::test_float_precision tests/test_writer.py::TestWriter::test_data[\x00-<00>] tests/test_writer.py::TestWriter::test_data[\x00\x01-<0001>] tests/test_writer.py::TestWriter::test_data[\x00\x01\x02-<000102>] tests/test_writer.py::TestWriter::test_data[\x00\x01\x02\x03-<00010203>] tests/test_writer.py::TestWriter::test_data[\x00\x01\x02\x03\x04-<00010203 tests/test_writer.py::TestWriter::test_data[\x00\x01\x02\x03\x04\x05-<00010203 tests/test_writer.py::TestWriter::test_data[\x00\x01\x02\x03\x04\x05\x06-<00010203 tests/test_writer.py::TestWriter::test_data[\x00\x01\x02\x03\x04\x05\x06\x07-<00010203 tests/test_writer.py::TestWriter::test_data[\x00\x01\x02\x03\x04\x05\x06\x07\x08-<00010203 tests/test_writer.py::TestWriter::test_data[\t\n\x0b\x0c\r\x0e\x0f\x10\x11-<090A0B0C tests/test_writer.py::TestWriter::test_bool tests/test_writer.py::TestWriter::test_array[array0-()-()] tests/test_writer.py::TestWriter::test_array[array1-()-()] tests/test_writer.py::TestWriter::test_array[array2-(1)-(\n tests/test_writer.py::TestWriter::test_array[array3-(1, tests/test_writer.py::TestWriter::test_array[array4-(1.2, tests/test_writer.py::TestWriter::test_array[array5-(1, tests/test_writer.py::TestWriter::test_array[array6-(<61>, tests/test_writer.py::TestWriter::test_array[array7-({a tests/test_writer.py::TestWriter::test_dictionary[dictionary0-{}-{}] tests/test_writer.py::TestWriter::test_dictionary[dictionary1-{}-{}] tests/test_writer.py::TestWriter::test_dictionary[dictionary2-{a tests/test_writer.py::TestWriter::test_dictionary[dictionary3-{"1" tests/test_writer.py::TestWriter::test_dictionary[dictionary4-{abc tests/test_writer.py::TestWriter::test_dictionary[dictionary5-{z tests/test_writer.py::TestWriter::test_type_error tests/test_writer.py::test_string_needs_quotes[ABCDEFGHIJKLMNOPQRSTUVWXYZ-False] tests/test_writer.py::test_string_needs_quotes[abcdefghijklmnopqrstuvwxyz-False] tests/test_writer.py::test_string_needs_quotes[a0123456789-False] tests/test_writer.py::test_string_needs_quotes[.appVersion-False] tests/test_writer.py::test_string_needs_quotes[_private-False] tests/test_writer.py::test_string_needs_quotes[$PWD-False] tests/test_writer.py::test_string_needs_quotes[1zzz-False] tests/test_writer.py::test_string_needs_quotes[192.168.1.1-False] tests/test_writer.py::test_string_needs_quotes[0-True] tests/test_writer.py::test_string_needs_quotes[1-True] tests/test_writer.py::test_string_needs_quotes[2-True] tests/test_writer.py::test_string_needs_quotes[3-True] tests/test_writer.py::test_string_needs_quotes[4-True] tests/test_writer.py::test_string_needs_quotes[5-True] tests/test_writer.py::test_string_needs_quotes[6-True] tests/test_writer.py::test_string_needs_quotes[7-True] tests/test_writer.py::test_string_needs_quotes[8-True] tests/test_writer.py::test_string_needs_quotes[9-True] tests/test_writer.py::test_string_needs_quotes[-True] tests/test_writer.py::test_string_needs_quotes[--True] tests/test_writer.py::test_string_needs_quotes[A-Z-True] tests/test_writer.py::test_string_needs_quotes[hello tests/test_writer.py::test_string_needs_quotes[\\backslash-True] tests/test_writer.py::test_string_needs_quotes[http://github.com-True] tests/test_writer.py::test_single_line_tuples