# Exporting notebooks inserts unwanted $CellContext. Workaround? [duplicate] Let's import a notebook: nb = ImportString["Notebook[{},TrackCellChangeTimes->False]", "NB"] (* Notebook[{}, TrackCellChangeTimes -> False] *)  All is well so far. Now let's re-export it: ExportString[nb, "NB"]  Now the output contains $CellContextTrackCellChangeTimes -> False


TrackCellChangeTimes -> False


This happens with every valid notebook or cell option that doesn't already have a corresponding symbol in the System context, and thus Import creates it in Global instead.

Why does this happen? What's a reasonable workaround?

Notes:

• I need the notebooks exported with full cache information, so I cannot export them as a plain expression.

• NotebookSave suffers from the same problem.

• The problem goes away if I use "TrackCellChangeTimes" (a string) instead of TrackCellChangeTimes.

However, cycling such a notebook expression through NotebookPut and NotebookGet "removes" the quotes and converts the string to a symbol again. Thus I do not know how to get strings for such options when importing a notebook.

• I am using Import/Export to post-process notebooks created by the documentation tools and fix things. The unwanted $CellContext causes subtle breakage that I did not even notice until now. • Should I delete my answer and make it a duplicate? Programming scripts to create and modify stylesheets – Kuba Nov 30 '16 at 19:32 • @Kuba Please don't delete, the duplicate is too long. This answer is clear an simple. Let's keep it as is. – Szabolcs Nov 30 '16 at 19:48 ## 1 Answer ## TL;DR; You can redirect unknown symbols to System which will be stripped later: Block[{$Context = "System"},
nb = ImportString["Notebook[{},TrackCellChangeTimes->False]", "NB"]
]


## Digging in boxes' (cell expressions)* typesetting

*in opposite to expressions typesetting e.g.: Globalsymbol -> RowBox[{"symbol"}]

That is acutally quite important part of typsetting. So when will the context be stripped? When will $CellContext appear? Here is a small test: sample = { {#, #, #2, "System"}, {#, #2, #2, "System"}, {#, "System", #2}, {#, #2, #2}, {#, #2, #2, "System", #} } & @@@ {{"JLink", "Global"}, {"Global", "JLink"}, {"System", "JLink"}, {"FrontEnd", "Global"} } // Flatten[#, 1] &;   result = Block[{$Context = #2, $ContextPath = {##3}}, Reap[ Module[{str}, str = ExportString[ Notebook[{}, Symbol[# <> "TrackCellChangeTimes"] -> False], "NB"]; str = StringToStream[str]; Sow[{#, #2, {##3}, Find[str, "TrackCellChangeTimes"]}]; Close[str]; ]][[-1, 1, 1]] ] & @@@ sample;  result // SortBy[Last] // TableForm[#, TableAlignments -> Right, TableHeadings -> {None, Style[#, Bold, 15] & /@ {"symbol's context", "$Context",  "$ContextPath", "exported string"}}] &  So the rules seem to be as follows: ### Which[ • Symbol's context is System? Leave only the symbol name. • Symbol's context is the same as current $Context?

Use \$CellContextsymbolName

• Is symbol's context Global,FrontEnd or any FrontEnd related?

Leave only the symbol name.

• True

Use symbol's full name.

### ]`

• It was of course WholeGroupCellOpener for me too. – Szabolcs Nov 30 '16 at 19:41
• @Szabolcs I've conducted a little investigation, have to go now. Tell me if I've missed something. – Kuba Nov 30 '16 at 20:39